Implement SocketUser= and SocketGroup= for [Socket]

Since we already allow defining the mode of AF_UNIX sockets and FIFO, it
makes sense to also allow specific user/group ownership of the socket
file for restricting access.
This commit is contained in:
Dave Reisner 2012-11-05 12:50:19 -05:00
parent edca2e2348
commit aea54018a5
6 changed files with 97 additions and 3 deletions

View File

@ -357,6 +357,30 @@
0666.</para></listitem>
</varlistentry>
<varlistentry>
<term><varname>SocketUser=</varname></term>
<listitem><para>If listening on a file system
socket or FIFO, this option specifies the
user owner of the created socket. When
defining this, keep in mind that name
switch services for user name lookups may
not be available. It is advisable to use a
numeric UID for this
setting.</para></listitem>
</varlistentry>
<varlistentry>
<term><varname>SocketGroup=</varname></term>
<listitem><para>If listening on a file system
socket or FIFO, this option specifies the
group owner of the created socket. When
defining this, keep in mind that name
switch services for group name lookups may
not be available. It is advisable to use a
numeric GID for this
setting.</para></listitem>
</varlistentry>
<varlistentry>
<term><varname>Accept=</varname></term>
<listitem><para>Takes a boolean

View File

@ -43,6 +43,8 @@
" <property name=\"BindToDevice\" type=\"s\" access=\"read\"/>\n" \
" <property name=\"DirectoryMode\" type=\"u\" access=\"read\"/>\n" \
" <property name=\"SocketMode\" type=\"u\" access=\"read\"/>\n" \
" <property name=\"SocketUser\" type=\"s\" access=\"read\"/>\n" \
" <property name=\"SocketGroup\" type=\"s\" access=\"read\"/>\n" \
" <property name=\"Accept\" type=\"b\" access=\"read\"/>\n" \
" <property name=\"KeepAlive\" type=\"b\" access=\"read\"/>\n" \
" <property name=\"Priority\" type=\"i\" access=\"read\"/>\n" \
@ -109,6 +111,8 @@ static const BusProperty bus_socket_properties[] = {
{ "BindToDevice", bus_property_append_string, "s", offsetof(Socket, bind_to_device), true },
{ "DirectoryMode", bus_property_append_mode, "u", offsetof(Socket, directory_mode) },
{ "SocketMode", bus_property_append_mode, "u", offsetof(Socket, socket_mode) },
{ "SocketUser", bus_property_append_string, "s", offsetof(Socket, socket_user), true },
{ "SocketGroup", bus_property_append_string, "s", offsetof(Socket, socket_group), true },
{ "Accept", bus_property_append_bool, "b", offsetof(Socket, accept) },
{ "KeepAlive", bus_property_append_bool, "b", offsetof(Socket, keep_alive) },
{ "Priority", bus_property_append_int, "i", offsetof(Socket, priority) },

View File

@ -189,6 +189,8 @@ Socket.ExecStopPost, config_parse_exec, SOCKET_EXEC
Socket.TimeoutSec, config_parse_usec, 0, offsetof(Socket, timeout_usec)
Socket.DirectoryMode, config_parse_mode, 0, offsetof(Socket, directory_mode)
Socket.SocketMode, config_parse_mode, 0, offsetof(Socket, socket_mode)
Socket.SocketUser, config_parse_string, 0, offsetof(Socket, socket_user)
Socket.SocketGroup, config_parse_string, 0, offsetof(Socket, socket_group)
Socket.Accept, config_parse_bool, 0, offsetof(Socket, accept)
Socket.MaxConnections, config_parse_unsigned, 0, offsetof(Socket, max_connections)
Socket.KeepAlive, config_parse_bool, 0, offsetof(Socket, keep_alive)

View File

@ -136,6 +136,12 @@ static void socket_done(Unit *u) {
free(s->smack_ip_in);
free(s->smack_ip_out);
free(s->socket_user);
s->socket_user = NULL;
free(s->socket_group);
s->socket_group = NULL;
unit_unwatch_timer(u, &s->timer_watch);
}
@ -449,6 +455,16 @@ static void socket_dump(Unit *u, FILE *f, const char *prefix) {
prefix, yes_no(s->pass_sec),
prefix, strna(s->tcp_congestion));
if (s->socket_user)
fprintf(f,
"SocketUser: %s\n",
s->socket_user);
if (s->socket_group)
fprintf(f,
"SocketGroup: %s\n",
s->socket_group);
if (s->control_pid > 0)
fprintf(f,
"%sControl PID: %lu\n",
@ -692,6 +708,9 @@ static void socket_close_fds(Socket *s) {
}
static void socket_apply_socket_options(Socket *s, int fd) {
uid_t uid = 0;
gid_t gid = 0;
assert(s);
assert(fd >= 0);
@ -775,6 +794,21 @@ static void socket_apply_socket_options(Socket *s, int fd) {
if (s->smack_ip_out)
if (fsetxattr(fd, "security.SMACK64IPOUT", s->smack_ip_out, strlen(s->smack_ip_out), 0) < 0)
log_error("fsetxattr(\"security.SMACK64IPOUT\"): %m");
if (s->socket_user &&
get_user_creds((const char **)&s->socket_user, &uid,
NULL, NULL, NULL) < 0) {
log_warning("failed to lookup user: %s", s->socket_user);
}
if (s->socket_group &&
get_group_creds((const char **)&s->socket_group, &gid) < 0) {
log_warning("failed to lookup group: %s", s->socket_group);
}
if ((uid != 0 || gid != 0) && fchown(fd, uid, gid) < 0) {
log_warning("failed to change ownership of socket");
}
}
static void socket_apply_fifo_options(Socket *s, int fd) {
@ -794,11 +828,15 @@ static int fifo_address_create(
const char *path,
mode_t directory_mode,
mode_t socket_mode,
const char *socket_user,
const char *socket_group,
int *_fd) {
int fd = -1, r = 0;
struct stat st;
mode_t old_mask;
uid_t uid = 0;
gid_t gid = 0;
assert(path);
assert(_fd);
@ -823,7 +861,8 @@ static int fifo_address_create(
goto fail;
}
if ((fd = open(path, O_RDWR|O_CLOEXEC|O_NOCTTY|O_NONBLOCK|O_NOFOLLOW)) < 0) {
fd = open(path, O_RDWR|O_CLOEXEC|O_NOCTTY|O_NONBLOCK|O_NOFOLLOW);
if (fd < 0) {
r = -errno;
goto fail;
}
@ -835,15 +874,35 @@ static int fifo_address_create(
goto fail;
}
if (socket_user &&
get_user_creds(&socket_user, &uid, NULL, NULL, NULL) < 0) {
r = -errno;
log_error("failed to lookup user: %s", socket_user);
goto fail;
}
if (socket_group &&
get_group_creds(&socket_group, &gid) < 0) {
r = -errno;
log_error("failed to lookup group: %s", socket_group);
goto fail;
}
if (!S_ISFIFO(st.st_mode) ||
(st.st_mode & 0777) != (socket_mode & ~old_mask) ||
st.st_uid != getuid() ||
st.st_gid != getgid()) {
st.st_uid != uid ||
st.st_gid != gid) {
r = -EEXIST;
goto fail;
}
if ((uid != 0 || gid != 0) && fchown(fd, uid, gid) < 0) {
r = -errno;
log_error("failed to changed ownership of FIFO: %s", path);
goto fail;
}
*_fd = fd;
return 0;
@ -1013,6 +1072,8 @@ static int socket_open_fds(Socket *s) {
p->path,
s->directory_mode,
s->socket_mode,
s->socket_user,
s->socket_group,
&p->fd)) < 0)
goto rollback;

View File

@ -118,6 +118,8 @@ struct Socket {
mode_t directory_mode;
mode_t socket_mode;
char *socket_user;
char *socket_group;
SocketResult result;

View File

@ -52,6 +52,7 @@ int socket_address_listen(
int *ret) {
int r, fd, one;
assert(a);
assert(ret);