--- Makefile.am | 5 +++ man/tmpfiles.d.xml | 32 ++++++++++++----- src/journal/coredump.c | 6 +--- src/journal/journalctl.c | 6 +--- src/journal/journald-server.c | 5 --- src/login/logind-acl.c | 2 -- src/shared/acl-util.c | 66 +++++++++++++++++++++++++++++++++-- src/shared/acl-util.h | 19 ++++++---- src/tmpfiles/tmpfiles.c | 81 +++++++++++++++++++++++++++++++++++++++++++ 9 files changed, 188 insertions(+), 34 deletions(-)
diff --git a/Makefile.am b/Makefile.am index ce5ebf7c48..d8b443e9dc 100644 --- a/Makefile.am +++ b/Makefile.am @@ -2189,6 +2189,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 8d806a41ea..7c1ef42c20 100644 --- a/man/tmpfiles.d.xml +++ b/man/tmpfiles.d.xml @@ -292,6 +292,13 @@ path. This can be useful for setting SMACK labels. </para></listitem> </varlistentry> + + <varlistentry> + <term><varname>a</varname></term> + <listitem><para>Set POSIX ACLs (access control lists) on the + specified path. This can be useful for allowing aditional + access to certain files.</para></listitem> + </varlistentry> </variablelist> <para>If the exclamation mark is used, this line is only safe of @@ -374,8 +381,8 @@ if omitted or when set to <literal>-</literal>, the file access mode will not be modified. This parameter is ignored for <varname>x</varname>, <varname>r</varname>, - <varname>R</varname>, <varname>L</varname>, <varname>t</varname> - lines.</para> + <varname>R</varname>, <varname>L</varname>, <varname>t</varname>, + and <varname>a</varname> lines.</para> <para>Optionally, if prefixed with <literal>~</literal>, 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 <literal>-</literal>, the default 0 (root) is used. For <varname>z</varname>, - <varname>Z</varname> lines, when omitted or when set to -, the - file ownership will not be modified. These parameters are - ignored for <varname>x</varname>, <varname>r</varname>, - <varname>R</varname>, <varname>L</varname>, <varname>t</varname> - lines.</para> + <varname>Z</varname> lines, when omitted or when set to + <literal>-</literal>, the file ownership will not be + modified. These parameters are ignored for <varname>x</varname>, + <varname>r</varname>, <varname>R</varname>, + <varname>L</varname>, <varname>t</varname>, and + <varname>a</varname> lines.</para> </refsect2> <refsect2> @@ -458,7 +466,8 @@ is written to the file, suffixed by a newline. For <varname>C</varname>, specifies the source file or directory. For <varname>t</varname> determines extended - attributes to be set. Ignored for all other lines.</para> + attributes to be set. For <varname>a</varname> determines + ACL attributes to be set. Ignored for all other lines.</para> </refsect2> </refsect1> @@ -489,7 +498,12 @@ <citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>, <citerefentry><refentrytitle>systemd-tmpfiles</refentrytitle><manvolnum>8</manvolnum></citerefentry>, <citerefentry><refentrytitle>systemd-delta</refentrytitle><manvolnum>1</manvolnum></citerefentry>, - <citerefentry><refentrytitle>systemd.exec</refentrytitle><manvolnum>5</manvolnum></citerefentry> + <citerefentry><refentrytitle>systemd.exec</refentrytitle><manvolnum>5</manvolnum></citerefentry>, + <citerefentry project='man-pages'><refentrytitle>attr</refentrytitle><manvolnum>5</manvolnum></citerefentry>, + <citerefentry project='man-pages'><refentrytitle>getfattr</refentrytitle><manvolnum>1</manvolnum></citerefentry>, + <citerefentry project='man-pages'><refentrytitle>setfattr</refentrytitle><manvolnum>1</manvolnum></citerefentry>, + <citerefentry project='man-pages'><refentrytitle>setfacl</refentrytitle><manvolnum>1</manvolnum></citerefentry>, + <citerefentry project='man-pages'><refentrytitle>getfacl</refentrytitle><manvolnum>1</manvolnum></citerefentry> </para> </refsect1> diff --git a/src/journal/coredump.c b/src/journal/coredump.c index a37e5eb8a7..d322e7984c 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 <sys/acl.h> -# 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 db9576c493..3d890ffb61 100644 --- a/src/journal/journalctl.c +++ b/src/journal/journalctl.c @@ -37,17 +37,13 @@ #include <sys/inotify.h> #include <linux/fs.h> -#ifdef HAVE_ACL -#include <sys/acl.h> -#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 5999724edc..87b459b3ca 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 <sys/acl.h> -#include <acl/libacl.h> #include "acl-util.h" -#endif #ifdef HAVE_SELINUX #include <selinux/selinux.h> diff --git a/src/login/logind-acl.c b/src/login/logind-acl.c index f7c6f3a4ef..5856f9079d 100644 --- a/src/login/logind-acl.c +++ b/src/login/logind-acl.c @@ -22,8 +22,6 @@ #include <assert.h> #include <errno.h> #include <string.h> -#include <sys/acl.h> -#include <acl/libacl.h> #include "util.h" #include "acl-util.h" diff --git a/src/shared/acl-util.c b/src/shared/acl-util.c index c93f58a739..22bb8444e5 100644 --- a/src/shared/acl-util.c +++ b/src/shared/acl-util.c @@ -20,8 +20,6 @@ ***/ #include <assert.h> -#include <sys/acl.h> -#include <acl/libacl.h> #include <errno.h> #include <stdbool.h> @@ -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 a753ad14fd..4133214d25 100644 --- a/src/shared/acl-util.h +++ b/src/shared/acl-util.h @@ -21,16 +21,23 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>. ***/ +#ifdef HAVE_ACL + #include <stdbool.h> +#include <sys/acl.h> +#include <acl/libacl.h> + +#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 c44dfaf1d2..7081b4dc57 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; -- 1.8.4.652.g0d6e0ce _______________________________________________ systemd-devel mailing list systemd-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/systemd-devel