Git init
[framework/base/acl.git] / packaging / 03-re-stat_file_after_chown.patch
1 commit 16230023e5afcb0b42b8d01207e3449d22772c31
2 Author: Brandon Philips <brandon@ifup.org>
3 Date:   Thu Dec 17 14:28:04 2009 -0800
4
5     setfacl: changing owner and when S_ISUID should be set --restore fix
6     
7     Fix a problem in setfacl --restore when the owner or group is changed
8     and the S_ISUID and S_ISGID are to be set.
9     
10     The root of the problem is that chown() can clear the S_ISUID and
11     S_ISGID bits as described in chown(2):
12     
13      When  the  owner  or  group of an executable file are changed by a
14      non- superuser, the S_ISUID and S_ISGID mode bits are cleared.   POSIX
15      does not specify whether this also should happen when root does the
16      chown(); the Linux behavior depends on the kernel version.  In case  of
17      a  non- group-executable  file (i.e., one for which the S_IXGRP bit is
18      not set) the S_ISGID bit indicates mandatory locking, and is not
19      cleared  by  a chown().
20     
21     To fix the issue re-stat() the file after chown() so that the logic
22     surrounding the chmod() has the updated mode of the file.
23     
24     Signed-off-by: Brandon Philips <bphilips@suse.de>
25
26 diff --git a/setfacl/setfacl.c b/setfacl/setfacl.c
27 index 091b9cc..56b0aa4 100644
28 --- a/setfacl/setfacl.c
29 +++ b/setfacl/setfacl.c
30 @@ -128,6 +128,7 @@ restore(
31         struct do_set_args args;
32         int line = 0, backup_line;
33         int error, status = 0;
34 +       int chmod_required = 0;
35  
36         memset(&st, 0, sizeof(st));
37  
38 @@ -206,10 +207,15 @@ restore(
39                                         strerror(errno));
40                                 status = 1;
41                         }
42 +
43 +                       /* chown() clears setuid/setgid so force a chmod if
44 +                        * S_ISUID/S_ISGID was expected */
45 +                       if ((st.st_mode & flags) & (S_ISUID | S_ISGID))
46 +                               chmod_required = 1;
47                 }
48  
49                 mask = S_ISUID | S_ISGID | S_ISVTX;
50 -               if ((st.st_mode & mask) != (flags & mask)) {
51 +               if (chmod_required || ((st.st_mode & mask) != (flags & mask))) {
52                         if (!args.mode)
53                                 args.mode = st.st_mode;
54                         args.mode &= (S_IRWXU | S_IRWXG | S_IRWXO);
55 diff --git a/test/root/restore.test b/test/root/restore.test
56 new file mode 100644
57 index 0000000..6003cd4
58 --- /dev/null
59 +++ b/test/root/restore.test
60 @@ -0,0 +1,23 @@
61 +Ensure setuid bit is restored when the owner changes
62 + https://bugzilla.redhat.com/show_bug.cgi?id=467936#c7
63 +
64 +       $ touch passwd
65 +       $ chmod 755 passwd
66 +       $ chmod u+s passwd
67 +       $ getfacl passwd > passwd.acl
68 +       $ cat passwd.acl
69 +       > # file: passwd
70 +       > # owner: root
71 +       > # group: root
72 +       > # flags: s--
73 +       > user::rwx
74 +       > group::r-x
75 +       > other::r-x
76 +       >
77 +       $ chown bin passwd
78 +       $ chmod u+s passwd
79 +       $ setfacl --restore passwd.acl
80 +       $ ls -dl passwd | awk '{print $1 " " $3 " " $4}'
81 +       > -rwsr-xr-x root root
82 +
83 +       $ rm passwd passwd.acl