socket: add new Symlinks= option for socket units
With Symlinks= we can manage one or more symlinks to AF_UNIX or FIFO nodes in the file system, with the same lifecycle as the socket itself. This has two benefits: first, this allows us to remove /dev/log and /dev/initctl from /dev, thus leaving only symlinks, device nodes and directories in the /dev tree. More importantly however, this allows us to move /dev/log out of /dev, while still making it accessible there, so that PrivateDevices= can provide /dev/log too.
This commit is contained in:
+66
-2
@@ -145,6 +145,8 @@ static void socket_done(Unit *u) {
|
||||
free(s->smack_ip_in);
|
||||
free(s->smack_ip_out);
|
||||
|
||||
strv_free(s->symlinks);
|
||||
|
||||
s->timer_event_source = sd_event_source_unref(s->timer_event_source);
|
||||
}
|
||||
|
||||
@@ -355,6 +357,39 @@ static int socket_add_extras(Socket *s) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const char *socket_find_symlink_target(Socket *s) {
|
||||
const char *found = NULL;
|
||||
SocketPort *p;
|
||||
|
||||
LIST_FOREACH(port, p, s->ports) {
|
||||
const char *f = NULL;
|
||||
|
||||
switch (p->type) {
|
||||
|
||||
case SOCKET_FIFO:
|
||||
f = p->path;
|
||||
break;
|
||||
|
||||
case SOCKET_SOCKET:
|
||||
if (p->address.sockaddr.un.sun_path[0] != 0)
|
||||
f = p->address.sockaddr.un.sun_path;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (f) {
|
||||
if (found)
|
||||
return NULL;
|
||||
|
||||
found = f;
|
||||
}
|
||||
}
|
||||
|
||||
return found;
|
||||
}
|
||||
|
||||
static int socket_verify(Socket *s) {
|
||||
assert(s);
|
||||
|
||||
@@ -387,6 +422,11 @@ static int socket_verify(Socket *s) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!strv_isempty(s->symlinks) && !socket_find_symlink_target(s)) {
|
||||
log_error_unit(UNIT(s)->id, "%s has symlinks set but none or more than one node in the file system. Refusing.", UNIT(s)->id);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -692,6 +732,7 @@ static int instance_from_socket(int fd, unsigned nr, char **instance) {
|
||||
|
||||
static void socket_close_fds(Socket *s) {
|
||||
SocketPort *p;
|
||||
char **i;
|
||||
|
||||
assert(s);
|
||||
|
||||
@@ -732,6 +773,10 @@ static void socket_close_fds(Socket *s) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (s->remove_on_stop)
|
||||
STRV_FOREACH(i, s->symlinks)
|
||||
unlink(*i);
|
||||
}
|
||||
|
||||
static void socket_apply_socket_options(Socket *s, int fd) {
|
||||
@@ -915,7 +960,8 @@ static int special_address_create(
|
||||
assert(path);
|
||||
assert(_fd);
|
||||
|
||||
if ((fd = open(path, O_RDONLY|O_CLOEXEC|O_NOCTTY|O_NONBLOCK|O_NOFOLLOW)) < 0) {
|
||||
fd = open(path, O_RDONLY|O_CLOEXEC|O_NOCTTY|O_NONBLOCK|O_NOFOLLOW);
|
||||
if (fd < 0) {
|
||||
r = -errno;
|
||||
goto fail;
|
||||
}
|
||||
@@ -968,7 +1014,6 @@ static int mq_address_create(
|
||||
|
||||
/* Include the original umask in our mask */
|
||||
umask(~mq_mode | old_mask);
|
||||
|
||||
fd = mq_open(path, O_RDONLY|O_CLOEXEC|O_NONBLOCK|O_CREAT, mq_mode, attr);
|
||||
umask(old_mask);
|
||||
|
||||
@@ -998,6 +1043,22 @@ fail:
|
||||
return r;
|
||||
}
|
||||
|
||||
static int socket_symlink(Socket *s) {
|
||||
const char *p;
|
||||
char **i;
|
||||
|
||||
assert(s);
|
||||
|
||||
p = socket_find_symlink_target(s);
|
||||
if (!p)
|
||||
return 0;
|
||||
|
||||
STRV_FOREACH(i, s->symlinks)
|
||||
symlink(p, *i);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int socket_open_fds(Socket *s) {
|
||||
SocketPort *p;
|
||||
int r;
|
||||
@@ -1045,6 +1106,7 @@ static int socket_open_fds(Socket *s) {
|
||||
|
||||
p->fd = r;
|
||||
socket_apply_socket_options(s, p->fd);
|
||||
socket_symlink(s);
|
||||
|
||||
} else if (p->type == SOCKET_SPECIAL) {
|
||||
|
||||
@@ -1065,6 +1127,8 @@ static int socket_open_fds(Socket *s) {
|
||||
goto rollback;
|
||||
|
||||
socket_apply_fifo_options(s, p->fd);
|
||||
socket_symlink(s);
|
||||
|
||||
} else if (p->type == SOCKET_MQUEUE) {
|
||||
|
||||
r = mq_address_create(
|
||||
|
||||
Reference in New Issue
Block a user