From: Zbigniew Jędrzejewski-Szmek Date: Sun, 18 Jan 2015 04:27:39 +0000 (-0500) Subject: tmpfiles: add 'a' type to set ACLs X-Git-Tag: v219~373 X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=commitdiff_plain;h=f8eeeaf9b783ebbab30672629abf3920db286811 tmpfiles: add 'a' type to set ACLs --- diff --git a/Makefile.am b/Makefile.am index e86075f23..440ba888a 100644 --- a/Makefile.am +++ b/Makefile.am @@ -2193,6 +2193,11 @@ systemd_tmpfiles_LDADD = \ libsystemd-internal.la \ libsystemd-shared.la +if HAVE_ACL +systemd_tmpfiles_LDADD += \ + libsystemd-acl.la +endif + rootbin_PROGRAMS += \ systemd-tmpfiles diff --git a/man/tmpfiles.d.xml b/man/tmpfiles.d.xml index 8d806a41e..7c1ef42c2 100644 --- a/man/tmpfiles.d.xml +++ b/man/tmpfiles.d.xml @@ -292,6 +292,13 @@ path. This can be useful for setting SMACK labels. + + + a + Set POSIX ACLs (access control lists) on the + specified path. This can be useful for allowing aditional + access to certain files. + If the exclamation mark is used, this line is only safe of @@ -374,8 +381,8 @@ if omitted or when set to -, the file access mode will not be modified. This parameter is ignored for x, r, - R, L, t - lines. + R, L, t, + and a lines. Optionally, if prefixed with ~, the access mode is masked based on the already set access bits for @@ -397,11 +404,12 @@ may either be a numeric user/group ID or a user or group name. If omitted or when set to -, the default 0 (root) is used. For z, - Z lines, when omitted or when set to -, the - file ownership will not be modified. These parameters are - ignored for x, r, - R, L, t - lines. + Z lines, when omitted or when set to + -, the file ownership will not be + modified. These parameters are ignored for x, + r, R, + L, t, and + a lines. @@ -458,7 +466,8 @@ is written to the file, suffixed by a newline. For C, specifies the source file or directory. For t determines extended - attributes to be set. Ignored for all other lines. + attributes to be set. For a determines + ACL attributes to be set. Ignored for all other lines. @@ -489,7 +498,12 @@ systemd1, systemd-tmpfiles8, systemd-delta1, - systemd.exec5 + systemd.exec5, + attr5, + getfattr1, + setfattr1, + setfacl1, + getfacl1 diff --git a/src/journal/coredump.c b/src/journal/coredump.c index a37e5eb8a..d322e7984 100644 --- a/src/journal/coredump.c +++ b/src/journal/coredump.c @@ -49,11 +49,7 @@ #include "path-util.h" #include "compress.h" #include "coredump-vacuum.h" - -#ifdef HAVE_ACL -# include -# include "acl-util.h" -#endif +#include "acl-util.h" /* The maximum size up to which we process coredumps */ #define PROCESS_SIZE_MAX ((off_t) (2LLU*1024LLU*1024LLU*1024LLU)) diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c index 27a6187e5..c17cf55c3 100644 --- a/src/journal/journalctl.c +++ b/src/journal/journalctl.c @@ -37,17 +37,13 @@ #include #include -#ifdef HAVE_ACL -#include -#include "acl-util.h" -#endif - #include "sd-journal.h" #include "sd-bus.h" #include "log.h" #include "logs-show.h" #include "util.h" +#include "acl-util.h" #include "path-util.h" #include "fileio.h" #include "build.h" diff --git a/src/journal/journald-server.c b/src/journal/journald-server.c index 5999724ed..87b459b3c 100644 --- a/src/journal/journald-server.c +++ b/src/journal/journald-server.c @@ -52,12 +52,7 @@ #include "journald-native.h" #include "journald-audit.h" #include "journald-server.h" - -#ifdef HAVE_ACL -#include -#include #include "acl-util.h" -#endif #ifdef HAVE_SELINUX #include diff --git a/src/login/logind-acl.c b/src/login/logind-acl.c index f7c6f3a4e..5856f9079 100644 --- a/src/login/logind-acl.c +++ b/src/login/logind-acl.c @@ -22,8 +22,6 @@ #include #include #include -#include -#include #include "util.h" #include "acl-util.h" diff --git a/src/shared/acl-util.c b/src/shared/acl-util.c index c93f58a73..22bb8444e 100644 --- a/src/shared/acl-util.c +++ b/src/shared/acl-util.c @@ -20,8 +20,6 @@ ***/ #include -#include -#include #include #include @@ -151,3 +149,67 @@ int search_acl_groups(char*** dst, const char* path, bool* belong) { return 0; } + +int parse_acl(char *text, acl_t *acl_access, acl_t *acl_default) { + _cleanup_free_ char **a = NULL, **d = NULL; /* strings are not be freed */ + _cleanup_strv_free_ char **split; + char **entry; + int r = -EINVAL; + _cleanup_(acl_freep) acl_t a_acl = NULL, d_acl = NULL; + + split = strv_split(text, ","); + if (!split) + return log_oom(); + + STRV_FOREACH(entry, split) { + char *p; + + p = startswith(*entry, "default:"); + if (!p) + p = startswith(*entry, "d:"); + + if (p) + r = strv_push(&d, p); + else + r = strv_push(&a, *entry); + } + if (r < 0) + return r; + + if (!strv_isempty(a)) { + _cleanup_free_ char *join; + + join = strv_join(a, ","); + if (!join) + return -ENOMEM; + + a_acl = acl_from_text(join); + if (!a_acl) + return -EINVAL; + + r = calc_acl_mask_if_needed(&a_acl); + if (r < 0) + return r; + } + + if (!strv_isempty(d)) { + _cleanup_free_ char *join; + + join = strv_join(d, ","); + if (!join) + return -ENOMEM; + + d_acl = acl_from_text(join); + if (!d_acl) + return -EINVAL; + + r = calc_acl_mask_if_needed(&d_acl); + if (r < 0) + return r; + } + + *acl_access = a_acl; + *acl_default = d_acl; + a_acl = d_acl = NULL; + return 0; +} diff --git a/src/shared/acl-util.h b/src/shared/acl-util.h index a753ad14f..4133214d2 100644 --- a/src/shared/acl-util.h +++ b/src/shared/acl-util.h @@ -21,16 +21,23 @@ along with systemd; If not, see . ***/ +#ifdef HAVE_ACL + #include +#include +#include + +#include "macro.h" int acl_find_uid(acl_t acl, uid_t uid, acl_entry_t *entry); int calc_acl_mask_if_needed(acl_t *acl_p); int search_acl_groups(char*** dst, const char* path, bool* belong); +int parse_acl(char *text, acl_t *acl_access, acl_t *acl_default); -static inline void acl_freep(acl_t *acl) { - - if (!*acl) - return; +/* acl_free takes multiple argument types. + * Multiple cleanup functions are necessary. */ +DEFINE_TRIVIAL_CLEANUP_FUNC(acl_t, acl_free); +#define acl_free_charp acl_free +DEFINE_TRIVIAL_CLEANUP_FUNC(char*, acl_free_charp); - acl_free(*acl); -} +#endif diff --git a/src/tmpfiles/tmpfiles.c b/src/tmpfiles/tmpfiles.c index c44dfaf1d..7081b4dc5 100644 --- a/src/tmpfiles/tmpfiles.c +++ b/src/tmpfiles/tmpfiles.c @@ -57,6 +57,7 @@ #include "copy.h" #include "selinux-util.h" #include "btrfs-util.h" +#include "acl-util.h" /* This reads all files listed in /etc/tmpfiles.d/?*.conf and creates * them in the file system. This is intended to be used to create @@ -76,6 +77,7 @@ typedef enum ItemType { CREATE_BLOCK_DEVICE = 'b', COPY_FILES = 'C', SET_XATTR = 't', + SET_ACL = 'a', /* These ones take globs */ WRITE_FILE = 'w', @@ -94,6 +96,10 @@ typedef struct Item { char *path; char *argument; char **xattrs; +#ifdef HAVE_ACL + acl_t acl_access; + acl_t acl_default; +#endif uid_t uid; gid_t gid; mode_t mode; @@ -581,6 +587,59 @@ static int item_set_xattrs(Item *i, const char *path) { return 0; } +static int get_acls_from_arg(Item *item) { +#ifdef HAVE_ACL + int r; + _cleanup_(acl_freep) acl_t a = NULL, d = NULL; + + assert(item); + + r = parse_acl(item->argument, &item->acl_access, &item->acl_default); + if (r < 0) + log_warning_errno(errno, "Failed to parse ACL \"%s\": %m. Ignoring", + item->argument); +#else + log_warning_errno(ENOSYS, "ACLs are not supported. Ignoring"); +#endif + + return 0; +} + +static int item_set_acl(Item *item, const char *path) { +#ifdef HAVE_ACL + int r; + + assert(item); + assert(path); + + if (item->acl_access) { + r = acl_set_file(path, ACL_TYPE_ACCESS, item->acl_access); + if (r < 0) { + _cleanup_(acl_free_charpp) char *t; + + t = acl_to_any_text(item->acl_access, NULL, ',', TEXT_ABBREVIATE); + return log_error_errno(errno, + "Setting access ACL \"%s\" on %s failed: %m", + strna(t), path); + } + } + + if (item->acl_default) { + r = acl_set_file(path, ACL_TYPE_DEFAULT, item->acl_default); + if (r < 0) { + _cleanup_(acl_free_charpp) char *t; + + t = acl_to_any_text(item->acl_default, NULL, ',', TEXT_ABBREVIATE); + return log_error_errno(errno, + "Setting default ACL \"%s\" on %s failed: %m", + strna(t), path); + } + } +#endif + + return 0; +} + static int write_one_file(Item *i, const char *path) { _cleanup_close_ int fd = -1; int flags, r = 0; @@ -974,6 +1033,11 @@ static int create_item(Item *i) { if (r < 0) return r; break; + + case SET_ACL: + r = item_set_acl(i, i->path); + if (r < 0) + return r; } log_debug("%s created successfully.", i->path); @@ -1004,6 +1068,7 @@ static int remove_item_instance(Item *i, const char *instance) { case WRITE_FILE: case COPY_FILES: case SET_XATTR: + case SET_ACL: break; case REMOVE_PATH: @@ -1049,6 +1114,7 @@ static int remove_item(Item *i) { case WRITE_FILE: case COPY_FILES: case SET_XATTR: + case SET_ACL: break; case REMOVE_PATH: @@ -1190,6 +1256,11 @@ static void item_free_contents(Item *i) { free(i->path); free(i->argument); strv_free(i->xattrs); + +#ifdef HAVE_ACL + acl_free(i->acl_access); + acl_free(i->acl_default); +#endif } static void item_array_free(ItemArray *a) { @@ -1396,6 +1467,16 @@ static int parse_line(const char *fname, unsigned line, const char *buffer) { return r; break; + case SET_ACL: + if (!i.argument) { + log_error("[%s:%u] Set ACLs requires argument.", fname, line); + return -EBADMSG; + } + r = get_acls_from_arg(&i); + if (r < 0) + return r; + break; + default: log_error("[%s:%u] Unknown command type '%c'.", fname, line, i.type); return -EBADMSG;