]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
tmpfiles: do 'X' bit check in an ACL-aware manner
authorMike Yuan <me@yhndnzj.com>
Tue, 5 Mar 2024 14:25:44 +0000 (22:25 +0800)
committerMike Yuan <me@yhndnzj.com>
Wed, 6 Mar 2024 19:18:46 +0000 (03:18 +0800)
Follow-up for 26d98cdd78cb5283f5771bd5866997acc494b067

I.e. stat() cannot be used here.

Also, before this commit, the 'X' is only applied if
the owner has execute bit set. Now it takes group and
other into consideration too. setfacl(1) also has
the same behavior.

src/tmpfiles/tmpfiles.c

index 0dd890958c651e5f9a56c442784997fd2c189c3f..ede5ca8a964ca24968342670bb0f81213d01f0ee 100644 (file)
@@ -1275,33 +1275,43 @@ static int parse_acl_cond_exec(
         assert(ret);
 
         if (!S_ISDIR(st->st_mode)) {
-                has_exec = st->st_mode & S_IXUSR;
+                _cleanup_(acl_freep) acl_t old = NULL;
 
-                if (!has_exec && append) {
-                        _cleanup_(acl_freep) acl_t old = NULL;
+                old = acl_get_file(path, ACL_TYPE_ACCESS);
+                if (!old)
+                        return -errno;
+
+                has_exec = false;
+
+                for (r = acl_get_entry(old, ACL_FIRST_ENTRY, &entry);
+                     r > 0;
+                     r = acl_get_entry(old, ACL_NEXT_ENTRY, &entry)) {
 
-                        old = acl_get_file(path, ACL_TYPE_ACCESS);
-                        if (!old)
+                        acl_tag_t tag;
+
+                        if (acl_get_tag_type(entry, &tag) < 0)
                                 return -errno;
 
-                        for (r = acl_get_entry(old, ACL_FIRST_ENTRY, &entry);
-                             r > 0;
-                             r = acl_get_entry(old, ACL_NEXT_ENTRY, &entry)) {
+                        if (tag == ACL_MASK)
+                                continue;
 
-                                if (acl_get_permset(entry, &permset) < 0)
-                                        return -errno;
+                        /* If not appending, skip ACL definitions */
+                        if (!append && IN_SET(tag, ACL_USER, ACL_GROUP))
+                                continue;
 
-                                r = acl_get_perm(permset, ACL_EXECUTE);
-                                if (r < 0)
-                                        return -errno;
-                                if (r > 0) {
-                                        has_exec = true;
-                                        break;
-                                }
-                        }
+                        if (acl_get_permset(entry, &permset) < 0)
+                                return -errno;
+
+                        r = acl_get_perm(permset, ACL_EXECUTE);
                         if (r < 0)
                                 return -errno;
+                        if (r > 0) {
+                                has_exec = true;
+                                break;
+                        }
                 }
+                if (r < 0)
+                        return -errno;
 
                 /* Check if we're about to set the execute bit in acl_access */
                 if (!has_exec && access) {