summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndreas Gruenbacher <agruen@suse.de>2009-05-29 00:03:33 +0200
committerAndreas Gruenbacher <agruen@suse.de>2009-06-08 12:56:47 +0200
commit45833cc34cb647ed76ecff8adf630385c1c4eee8 (patch)
treefd1c6d9427fa18dbe51fde1b7ba020d71af185d3
parent766ec9211f550128e2df883f2aaad58b51d208d1 (diff)
downloadacl-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/CHANGES6
-rw-r--r--setfacl/setfacl.c22
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),