diff options
-rw-r--r-- | libdiskfs/file-chmod.c | 27 |
1 files changed, 18 insertions, 9 deletions
diff --git a/libdiskfs/file-chmod.c b/libdiskfs/file-chmod.c index c5228d13..6e92822c 100644 --- a/libdiskfs/file-chmod.c +++ b/libdiskfs/file-chmod.c @@ -1,5 +1,5 @@ /* libdiskfs implementation of fs.defs: file_chmod - Copyright (C) 1992, 1993, 1994 Free Software Foundation + Copyright (C) 1992, 1993, 1994, 1995 Free Software Foundation This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as @@ -22,21 +22,30 @@ error_t diskfs_S_file_chmod (struct protid *cred, mode_t mode) { + struct userid *id; + mode &= ~(S_IFMT | S_ISPARE); CHANGE_NODE_FIELD (cred, ({ if (!(err = diskfs_isowner (np, cred))) { - if (!diskfs_isuid (0, cred)) + /* Run through each ID in the chain + to see if it is allowed to do the operations + requested. Turn off bits as we find + that they are prohibited. */ + assert (cred->id); + for (id = cred->id; id; id = id->next) { - if (!S_ISDIR (np->dn_stat.st_mode)) - mode &= ~S_ISVTX; - if (!diskfs_groupmember (np->dn_stat.st_gid, - cred)) - mode &= ~S_ISGID; - if (!diskfs_isuid (np->dn_stat.st_uid, cred)) - mode &= ~S_ISUID; + if (!_diskfs_idhasuid (0, id)) + { + if (!S_ISDIR (np->dn_stat.st_mode)) + mode &= ~S_ISVTX; + if (!diskfs_idhasgid (np->dn_stat.st_gid, id)) + mode &= ~S_ISGID; + if (!diskfs_idhasuid (np->dn_stat.st_uid, id)) + mode &= ~S_ISUID; + } } mode |= (np->dn_stat.st_mode & (S_IFMT | S_ISPARE)); np->dn_stat.st_mode = mode; |