diff options
author | Andreas Gruenbacher <agruen@suse.de> | 2009-05-29 00:03:33 +0200 |
---|---|---|
committer | Andreas Gruenbacher <agruen@suse.de> | 2009-06-08 12:56:47 +0200 |
commit | 45833cc34cb647ed76ecff8adf630385c1c4eee8 (patch) | |
tree | fd1c6d9427fa18dbe51fde1b7ba020d71af185d3 | |
parent | 766ec9211f550128e2df883f2aaad58b51d208d1 (diff) | |
download | acl-45833cc34cb647ed76ecff8adf630385c1c4eee8.tar.gz |
Avoid unnecessary but destructive chown calls
When restoring acls and the file ownership from the output of getfacl
with setfacl --restore, make sure to only chown(2) files when the
owner or owning group does not match the current owner or owning group:
otherwise, if the caller does not have the appropriate privilege,
chown(2) will implicitly clear the suid and sgit flags.
-rw-r--r-- | doc/CHANGES | 6 | ||||
-rw-r--r-- | setfacl/setfacl.c | 22 |
2 files changed, 20 insertions, 8 deletions
diff --git a/doc/CHANGES b/doc/CHANGES index b1ac1ce..560d98d 100644 --- a/doc/CHANGES +++ b/doc/CHANGES @@ -1,3 +1,9 @@ +* When restoring acls and the file ownership from the output of getfacl + with setfacl --restore, make sure to only chown(2) files when the + owner or owning group does not match the current owner or owning group: + otherwise, if the caller does not have the appropriate privilege, + chown(2) will implicitly clear the suid and sgid flags. + 2.2.49 * Fix attr/acl code for handling of recursive walking without following symlinks Patch contributed by Brandon Philips <brandon@ifup.org>. diff --git a/setfacl/setfacl.c b/setfacl/setfacl.c index ed09538..7d94350 100644 --- a/setfacl/setfacl.c +++ b/setfacl/setfacl.c @@ -122,14 +122,14 @@ restore( const char *filename) { char *path_p; - struct stat stat; + struct stat st; uid_t uid; gid_t gid; seq_t seq = NULL; int line = 0, backup_line; int error, status = 0; - memset(&stat, 0, sizeof(stat)); + memset(&st, 0, sizeof(st)); for(;;) { backup_line = line; @@ -174,24 +174,30 @@ restore( goto getout; } - error = lstat(path_p, &stat); + error = stat(path_p, &st); if (opt_test && error != 0) { fprintf(stderr, "%s: %s: %s\n", progname, xquote(path_p), strerror(errno)); status = 1; } - stat.st_uid = uid; - stat.st_gid = gid; - error = do_set(path_p, &stat, 0, seq); + error = do_set(path_p, &st, 0, seq); if (error != 0) { status = 1; goto resume; } + if (uid != ACL_UNDEFINED_ID && uid != st.st_uid) + st.st_uid = uid; + else + st.st_uid = -1; + if (gid != ACL_UNDEFINED_ID && gid != st.st_gid) + st.st_gid = gid; + else + st.st_gid = -1; if (!opt_test && - (uid != ACL_UNDEFINED_ID || gid != ACL_UNDEFINED_ID)) { - if (chown(path_p, uid, gid) != 0) { + (st.st_uid != -1 || st.st_gid != -1)) { + if (chown(path_p, st.st_uid, st.st_gid) != 0) { fprintf(stderr, _("%s: %s: Cannot change " "owner/group: %s\n"), progname, xquote(path_p), |