Kamil Dudka b4fdf5
From 16230023e5afcb0b42b8d01207e3449d22772c31 Mon Sep 17 00:00:00 2001
Kamil Dudka b4fdf5
From: Brandon Philips <brandon@ifup.org>
Kamil Dudka b4fdf5
Date: Thu, 17 Dec 2009 14:28:04 -0800
Kamil Dudka b4fdf5
Subject: [PATCH] setfacl: changing owner and when S_ISUID should be set --restore fix
Kamil Dudka b4fdf5
Kamil Dudka b4fdf5
Fix a problem in setfacl --restore when the owner or group is changed
Kamil Dudka b4fdf5
and the S_ISUID and S_ISGID are to be set.
Kamil Dudka b4fdf5
Kamil Dudka b4fdf5
The root of the problem is that chown() can clear the S_ISUID and
Kamil Dudka b4fdf5
S_ISGID bits as described in chown(2):
Kamil Dudka b4fdf5
Kamil Dudka b4fdf5
 When  the  owner  or  group of an executable file are changed by a
Kamil Dudka b4fdf5
 non- superuser, the S_ISUID and S_ISGID mode bits are cleared.   POSIX
Kamil Dudka b4fdf5
 does not specify whether this also should happen when root does the
Kamil Dudka b4fdf5
 chown(); the Linux behavior depends on the kernel version.  In case  of
Kamil Dudka b4fdf5
 a  non- group-executable  file (i.e., one for which the S_IXGRP bit is
Kamil Dudka b4fdf5
 not set) the S_ISGID bit indicates mandatory locking, and is not
Kamil Dudka b4fdf5
 cleared  by  a chown().
Kamil Dudka b4fdf5
Kamil Dudka b4fdf5
To fix the issue re-stat() the file after chown() so that the logic
Kamil Dudka b4fdf5
surrounding the chmod() has the updated mode of the file.
Kamil Dudka b4fdf5
Kamil Dudka b4fdf5
Signed-off-by: Brandon Philips <bphilips@suse.de>
Kamil Dudka b4fdf5
---
Kamil Dudka b4fdf5
 setfacl/setfacl.c      |    8 +++++++-
Kamil Dudka b4fdf5
 test/root/restore.test |   23 +++++++++++++++++++++++
Kamil Dudka b4fdf5
 2 files changed, 30 insertions(+), 1 deletions(-)
Kamil Dudka b4fdf5
 create mode 100644 test/root/restore.test
Kamil Dudka b4fdf5
Kamil Dudka b4fdf5
diff --git a/setfacl/setfacl.c b/setfacl/setfacl.c
Kamil Dudka b4fdf5
index 091b9cc..56b0aa4 100644
Kamil Dudka b4fdf5
--- a/setfacl/setfacl.c
Kamil Dudka b4fdf5
+++ b/setfacl/setfacl.c
Kamil Dudka b4fdf5
@@ -128,6 +128,7 @@ restore(
Kamil Dudka b4fdf5
 	struct do_set_args args;
Kamil Dudka b4fdf5
 	int line = 0, backup_line;
Kamil Dudka b4fdf5
 	int error, status = 0;
Kamil Dudka b4fdf5
+	int chmod_required = 0;
Kamil Dudka b4fdf5
 
Kamil Dudka b4fdf5
 	memset(&st, 0, sizeof(st));
Kamil Dudka b4fdf5
 
Kamil Dudka b4fdf5
@@ -206,10 +207,15 @@ restore(
Kamil Dudka b4fdf5
 					strerror(errno));
Kamil Dudka b4fdf5
 				status = 1;
Kamil Dudka b4fdf5
 			}
Kamil Dudka b4fdf5
+
Kamil Dudka b4fdf5
+			/* chown() clears setuid/setgid so force a chmod if
Kamil Dudka b4fdf5
+			 * S_ISUID/S_ISGID was expected */
Kamil Dudka b4fdf5
+			if ((st.st_mode & flags) & (S_ISUID | S_ISGID))
Kamil Dudka b4fdf5
+				chmod_required = 1;
Kamil Dudka b4fdf5
 		}
Kamil Dudka b4fdf5
 
Kamil Dudka b4fdf5
 		mask = S_ISUID | S_ISGID | S_ISVTX;
Kamil Dudka b4fdf5
-		if ((st.st_mode & mask) != (flags & mask)) {
Kamil Dudka b4fdf5
+		if (chmod_required || ((st.st_mode & mask) != (flags & mask))) {
Kamil Dudka b4fdf5
 			if (!args.mode)
Kamil Dudka b4fdf5
 				args.mode = st.st_mode;
Kamil Dudka b4fdf5
 			args.mode &= (S_IRWXU | S_IRWXG | S_IRWXO);
Kamil Dudka b4fdf5
diff --git a/test/root/restore.test b/test/root/restore.test
Kamil Dudka b4fdf5
new file mode 100644
Kamil Dudka b4fdf5
index 0000000..6003cd4
Kamil Dudka b4fdf5
--- /dev/null
Kamil Dudka b4fdf5
+++ b/test/root/restore.test
Kamil Dudka b4fdf5
@@ -0,0 +1,23 @@
Kamil Dudka b4fdf5
+Ensure setuid bit is restored when the owner changes
Kamil Dudka b4fdf5
+ https://bugzilla.redhat.com/show_bug.cgi?id=467936#c7
Kamil Dudka b4fdf5
+
Kamil Dudka b4fdf5
+	$ touch passwd
Kamil Dudka b4fdf5
+	$ chmod 755 passwd
Kamil Dudka b4fdf5
+	$ chmod u+s passwd
Kamil Dudka b4fdf5
+	$ getfacl passwd > passwd.acl
Kamil Dudka b4fdf5
+	$ cat passwd.acl
Kamil Dudka b4fdf5
+	> # file: passwd
Kamil Dudka b4fdf5
+	> # owner: root
Kamil Dudka b4fdf5
+	> # group: root
Kamil Dudka b4fdf5
+	> # flags: s--
Kamil Dudka b4fdf5
+	> user::rwx
Kamil Dudka b4fdf5
+	> group::r-x
Kamil Dudka b4fdf5
+	> other::r-x
Kamil Dudka b4fdf5
+	>
Kamil Dudka b4fdf5
+	$ chown bin passwd
Kamil Dudka b4fdf5
+	$ chmod u+s passwd
Kamil Dudka b4fdf5
+	$ setfacl --restore passwd.acl
Kamil Dudka b4fdf5
+	$ ls -dl passwd | awk '{print $1 " " $3 " " $4}'
Kamil Dudka b4fdf5
+	> -rwsr-xr-x root root
Kamil Dudka b4fdf5
+
Kamil Dudka b4fdf5
+	$ rm passwd passwd.acl
Kamil Dudka b4fdf5
-- 
Kamil Dudka b4fdf5
1.6.2.5
Kamil Dudka b4fdf5