summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--man/tmpfiles.d.xml32
-rw-r--r--src/tmpfiles/tmpfiles.c139
2 files changed, 155 insertions, 16 deletions
diff --git a/man/tmpfiles.d.xml b/man/tmpfiles.d.xml
index 1b14d69a91..4f2e6406a8 100644
--- a/man/tmpfiles.d.xml
+++ b/man/tmpfiles.d.xml
@@ -343,6 +343,25 @@ L /tmp/foobar - - - - /dev/null</programlisting>
normal path
names.</para></listitem>
</varlistentry>
+
+ <varlistentry>
+ <term><varname>t</varname></term>
+ <listitem><para>Set extended
+ attributes on item. It may be
+ used in conjunction with other
+ types (only <varname>d</varname>,
+ <varname>D</varname>, <varname>f</varname>,
+ <varname>F</varname>, <varname>L</varname>,
+ <varname>p</varname>, <varname>c</varname>,
+ <varname>b</varname>, makes sense).
+ If used as a standalone line, then
+ <command>systemd-tmpfiles</command>
+ will try to set extended
+ attributes on specified path.
+ This can be especially used to set
+ SMACK labels.
+ </para></listitem>
+ </varlistentry>
</variablelist>
<para>If the exclamation mark is used, this
@@ -430,7 +449,7 @@ r! /tmp/.X[0-9]*-lock</programlisting>
will not be modified. This parameter is
ignored for <varname>x</varname>,
<varname>r</varname>, <varname>R</varname>,
- <varname>L</varname> lines.</para>
+ <varname>L</varname>, <varname>t</varname> lines.</para>
<para>Optionally, if prefixed with
<literal>~</literal>, the access mode is masked
@@ -462,8 +481,8 @@ r! /tmp/.X[0-9]*-lock</programlisting>
ownership will not be modified. These
parameters are ignored for
<varname>x</varname>, <varname>r</varname>,
- <varname>R</varname>, <varname>L</varname>
- lines.</para>
+ <varname>R</varname>, <varname>L</varname>,
+ <varname>t</varname> lines.</para>
</refsect2>
<refsect2>
@@ -527,8 +546,8 @@ r! /tmp/.X[0-9]*-lock</programlisting>
specify a short string that is written to the
file, suffixed by a newline. For
<varname>C</varname>, specifies the source file
- or directory. Ignored for all other
- lines.</para>
+ or directory. For <varname>t</varname> determines
+ extended attributes to be set. Ignored for all other lines.</para>
</refsect2>
</refsect1>
@@ -540,7 +559,8 @@ r! /tmp/.X[0-9]*-lock</programlisting>
<para><command>screen</command> needs two directories created at boot with specific modes and ownership.</para>
<programlisting>d /run/screens 1777 root root 10d
-d /run/uscreens 0755 root root 10d12h</programlisting>
+d /run/uscreens 0755 root root 10d12h
+t /run/screen - - - - user.name="John Smith" security.SMACK64=screen</programlisting>
</example>
<example>
<title>/etc/tmpfiles.d/abrt.conf example</title>
diff --git a/src/tmpfiles/tmpfiles.c b/src/tmpfiles/tmpfiles.c
index d60c57793b..d40bd96f1b 100644
--- a/src/tmpfiles/tmpfiles.c
+++ b/src/tmpfiles/tmpfiles.c
@@ -39,6 +39,7 @@
#include <glob.h>
#include <fnmatch.h>
#include <sys/capability.h>
+#include <sys/xattr.h>
#include "log.h"
#include "util.h"
@@ -71,6 +72,7 @@ typedef enum ItemType {
CREATE_CHAR_DEVICE = 'c',
CREATE_BLOCK_DEVICE = 'b',
COPY_FILES = 'C',
+ SET_XATTR = 't',
/* These ones take globs */
WRITE_FILE = 'w',
@@ -88,6 +90,7 @@ typedef struct Item {
char *path;
char *argument;
+ char **xattrs;
uid_t uid;
gid_t gid;
mode_t mode;
@@ -487,6 +490,67 @@ static int item_set_perms(Item *i, const char *path) {
return label_fix(path, false, false);
}
+static int get_xattrs_from_arg(Item *i) {
+ char *xattr;
+ const char *p;
+ int r;
+
+ assert(i);
+
+ if (!i->argument) {
+ log_error("%s: Argument can't be empty!", i->path);
+ return -EBADMSG;
+ }
+ p = i->argument;
+
+ while ((r = unquote_first_word(&p, &xattr, false)) > 0) {
+ _cleanup_free_ char *tmp = NULL, *name = NULL, *value = NULL;
+ r = split_pair(xattr, "=", &name, &value);
+ if (r < 0) {
+ log_warning("Illegal xattr found: \"%s\" - ignoring.", xattr);
+ free(xattr);
+ continue;
+ }
+ free(xattr);
+ if (streq(name, "") || streq(value, "")) {
+ log_warning("Malformed xattr found: \"%s=%s\" - ignoring.", name, value);
+ continue;
+ }
+ tmp = unquote(value, "\"");
+ if (!tmp)
+ return log_oom();
+ free(value);
+ value = cunescape(tmp);
+ if (!value)
+ return log_oom();
+ if (strv_consume_pair(&i->xattrs, name, value) < 0)
+ return log_oom();
+ name = value = NULL;
+ }
+
+ return r;
+}
+
+static int item_set_xattrs(Item *i, const char *path) {
+ char **name, **value;
+
+ assert(i);
+ assert(path);
+
+ if (strv_isempty(i->xattrs))
+ return 0;
+
+ STRV_FOREACH_PAIR(name, value, i->xattrs) {
+ int n;
+ n = strlen(*value);
+ if (lsetxattr(path, *name, *value, n, 0) < 0) {
+ log_error("Setting extended attribute %s=%s on %s failed: %m", *name, *value, path);
+ return -errno;
+ }
+ }
+ return 0;
+}
+
static int write_one_file(Item *i, const char *path) {
_cleanup_close_ int fd = -1;
int flags, r = 0;
@@ -544,6 +608,10 @@ static int write_one_file(Item *i, const char *path) {
if (r < 0)
return r;
+ r = item_set_xattrs(i, i->path);
+ if (r < 0)
+ return r;
+
return 0;
}
@@ -716,6 +784,10 @@ static int create_item(Item *i) {
if (r < 0)
return r;
+ r = item_set_xattrs(i, i->path);
+ if (r < 0)
+ return r;
+
break;
case CREATE_FIFO:
@@ -756,6 +828,10 @@ static int create_item(Item *i) {
if (r < 0)
return r;
+ r = item_set_xattrs(i, i->path);
+ if (r < 0)
+ return r;
+
break;
case CREATE_SYMLINK:
@@ -787,6 +863,10 @@ static int create_item(Item *i) {
}
}
+ r = item_set_xattrs(i, i->path);
+ if (r < 0)
+ return r;
+
break;
case CREATE_BLOCK_DEVICE:
@@ -847,6 +927,10 @@ static int create_item(Item *i) {
if (r < 0)
return r;
+ r = item_set_xattrs(i, i->path);
+ if (r < 0)
+ return r;
+
break;
}
@@ -863,7 +947,12 @@ static int create_item(Item *i) {
r = glob_item(i, item_set_perms_recursive);
if (r < 0)
return r;
+ break;
+ case SET_XATTR:
+ r = item_set_xattrs(i, i->path);
+ if (r < 0)
+ return r;
break;
}
@@ -893,6 +982,7 @@ static int remove_item_instance(Item *i, const char *instance) {
case RECURSIVE_RELABEL_PATH:
case WRITE_FILE:
case COPY_FILES:
+ case SET_XATTR:
break;
case REMOVE_PATH:
@@ -936,6 +1026,7 @@ static int remove_item(Item *i) {
case RECURSIVE_RELABEL_PATH:
case WRITE_FILE:
case COPY_FILES:
+ case SET_XATTR:
break;
case REMOVE_PATH:
@@ -1059,6 +1150,7 @@ static void item_free(Item *i) {
free(i->path);
free(i->argument);
+ strv_free(i->xattrs);
free(i);
}
@@ -1257,6 +1349,16 @@ static int parse_line(const char *fname, unsigned line, const char *buffer) {
break;
}
+ case SET_XATTR:
+ if (!i->argument) {
+ log_error("[%s:%u] Set extended attribute requires argument.", fname, line);
+ return -EBADMSG;
+ }
+ r = get_xattrs_from_arg(i);
+ if (r < 0)
+ return r;
+ break;
+
default:
log_error("[%s:%u] Unknown command type '%c'.", fname, line, type);
return -EBADMSG;
@@ -1350,18 +1452,35 @@ static int parse_line(const char *fname, unsigned line, const char *buffer) {
existing = hashmap_get(h, i->path);
if (existing) {
-
- /* Two identical items are fine */
- if (!item_equal(existing, i))
- log_warning("Two or more conflicting lines for %s configured, ignoring.", i->path);
-
- return 0;
+ if (i->type == SET_XATTR) {
+ r = strv_extend_strv(&existing->xattrs, i->xattrs);
+ if (r < 0)
+ return log_oom();
+ return 0;
+ } else if (existing->type == SET_XATTR) {
+ r = strv_extend_strv(&i->xattrs, existing->xattrs);
+ if (r < 0)
+ return log_oom();
+ r = hashmap_replace(h, i->path, i);
+ if (r < 0) {
+ log_error("Failed to replace item for %s.", i->path);
+ return r;
+ }
+ item_free(existing);
+ } else {
+ /* Two identical items are fine */
+ if (!item_equal(existing, i))
+ log_warning("Two or more conflicting lines for %s configured, ignoring.", i->path);
+ return 0;
+ }
+ } else {
+ r = hashmap_put(h, i->path, i);
+ if (r < 0) {
+ log_error("Failed to insert item %s: %s", i->path, strerror(-r));
+ return r;
+ }
}
- r = hashmap_put(h, i->path, i);
- if (r < 0)
- return log_error_errno(r, "Failed to insert item %s: %m", i->path);
-
i = NULL; /* avoid cleanup */
return 0;