]>
git.ipfire.org Git - thirdparty/systemd.git/blob - src/core/dynamic-user.c
2 This file is part of systemd.
4 Copyright 2016 Lennart Poettering
6 systemd is free software; you can redistribute it and/or modify it
7 under the terms of the GNU Lesser General Public License as published by
8 the Free Software Foundation; either version 2.1 of the License, or
9 (at your option) any later version.
11 systemd is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
16 You should have received a copy of the GNU Lesser General Public License
17 along with systemd; If not, see <http://www.gnu.org/licenses/>.
24 #include "dynamic-user.h"
27 #include "parse-util.h"
28 #include "random-util.h"
29 #include "stdio-util.h"
30 #include "string-util.h"
31 #include "user-util.h"
34 /* Let's pick a UIDs within the 16bit range, so that we are compatible with containers using 16bit user namespacing. At
35 * least on Fedora normal users are allocated until UID 60000, hence do not allocate from below this. Also stay away
36 * from the upper end of the range as that is often used for overflow/nobody users. */
37 #define UID_PICK_MIN ((uid_t) UINT32_C(0x0000EF00))
38 #define UID_PICK_MAX ((uid_t) UINT32_C(0x0000FFEF))
40 /* Takes a value generated randomly or by hashing and turns it into a UID in the right range */
41 #define UID_CLAMP_INTO_RANGE(rnd) (((uid_t) (rnd) % (UID_PICK_MAX - UID_PICK_MIN + 1)) + UID_PICK_MIN)
43 static DynamicUser
* dynamic_user_free ( DynamicUser
* d
) {
48 ( void ) hashmap_remove ( d
-> manager
-> dynamic_users
, d
-> name
);
50 safe_close_pair ( d
-> storage_socket
);
56 static int dynamic_user_add ( Manager
* m
, const char * name
, int storage_socket
[ 2 ], DynamicUser
** ret
) {
57 DynamicUser
* d
= NULL
;
62 assert ( storage_socket
);
64 r
= hashmap_ensure_allocated (& m
-> dynamic_users
, & string_hash_ops
);
68 d
= malloc0 ( offsetof ( DynamicUser
, name
) + strlen ( name
) + 1 );
72 strcpy ( d
-> name
, name
);
74 d
-> storage_socket
[ 0 ] = storage_socket
[ 0 ];
75 d
-> storage_socket
[ 1 ] = storage_socket
[ 1 ];
77 r
= hashmap_put ( m
-> dynamic_users
, d
-> name
, d
);
91 int dynamic_user_acquire ( Manager
* m
, const char * name
, DynamicUser
** ret
) {
92 _cleanup_close_pair_
int storage_socket
[ 2 ] = { - 1 , - 1 };
99 /* Return the DynamicUser structure for a specific user name. Note that this won't actually allocate a UID for
100 * it, but just prepare the data structure for it. The UID is allocated only on demand, when it's really
101 * needed, and in the child process we fork off, since allocation involves NSS checks which are not OK to do
102 * from PID 1. To allow the children and PID 1 share information about allocated UIDs we use an anonymous
103 * AF_UNIX/SOCK_DGRAM socket (called the "storage socket") that contains at most one datagram with the
104 * allocated UID number, plus an fd referencing the lock file for the UID
105 * (i.e. /run/systemd/dynamic-uid/$UID). Why involve the socket pair? So that PID 1 and all its children can
106 * share the same storage for the UID and lock fd, simply by inheriting the storage socket fds. The socket pair
107 * may exist in three different states:
109 * a) no datagram stored. This is the initial state. In this case the dynamic user was never realized.
111 * b) a datagram containing a UID stored, but no lock fd attached to it. In this case there was already a
112 * statically assigned UID by the same name, which we are reusing.
114 * c) a datagram containing a UID stored, and a lock fd is attached to it. In this case we allocated a dynamic
115 * UID and locked it in the file system, using the lock fd.
117 * As PID 1 and various children might access the socket pair simultaneously, and pop the datagram or push it
118 * back in any time, we also maintain a lock on the socket pair. Note one peculiarity regarding locking here:
119 * the UID lock on disk is protected via a BSD file lock (i.e. an fd-bound lock), so that the lock is kept in
120 * place as long as there's a reference to the fd open. The lock on the storage socket pair however is a POSIX
121 * file lock (i.e. a process-bound lock), as all users share the same fd of this (after all it is anonymous,
122 * nobody else could get any access to it except via our own fd) and we want to synchronize access between all
123 * processes that have access to it. */
125 d
= hashmap_get ( m
-> dynamic_users
, name
);
127 /* We already have a structure for the dynamic user, let's increase the ref count and reuse it */
133 if (! valid_user_group_name_or_id ( name
))
136 if ( socketpair ( AF_UNIX
, SOCK_DGRAM
| SOCK_CLOEXEC
, 0 , storage_socket
) < 0 )
139 r
= dynamic_user_add ( m
, name
, storage_socket
, & d
);
143 storage_socket
[ 0 ] = storage_socket
[ 1 ] = - 1 ;
153 static int make_uid_symlinks ( uid_t uid
, const char * name
, bool b
) {
155 char path1
[ strlen ( "/run/systemd/dynamic-uid/direct:" ) + DECIMAL_STR_MAX ( uid_t
) + 1 ];
159 /* Add direct additional symlinks for direct lookups of dynamic UIDs and their names by userspace code. The
160 * only reason we have this is because dbus-daemon cannot use D-Bus for resolving users and groups (since it
161 * would be its own client then). We hence keep these world-readable symlinks in place, so that the
162 * unprivileged dbus user can read the mappings when it needs them via these symlinks instead of having to go
163 * via the bus. Ideally, we'd use the lock files we keep for this anyway, but we can't since we use BSD locks
164 * on them and as those may be taken by any user with read access we can't make them world-readable. */
166 xsprintf ( path1
, "/run/systemd/dynamic-uid/direct:" UID_FMT
, uid
);
167 if ( unlink ( path1
) < 0 ) {
172 if ( symlink ( name
, path1
) < 0 )
176 path2
= strjoina ( "/run/systemd/dynamic-uid/direct:" , name
);
177 if ( unlink ( path2
) < 0 ) {
182 if ( symlink ( path1
+ strlen ( "/run/systemd/dynamic-uid/direct:" ), path2
) < 0 )
189 static int pick_uid ( const char * name
, uid_t
* ret_uid
) {
191 static const uint8_t hash_key
[] = {
192 0x37 , 0x53 , 0x7e , 0x31 , 0xcf , 0xce , 0x48 , 0xf5 ,
193 0x8a , 0xbb , 0x39 , 0x57 , 0x8d , 0xd9 , 0xec , 0x59
196 unsigned n_tries
= 100 ;
200 /* A static user by this name does not exist yet. Let's find a free ID then, and use that. We start with a UID
201 * generated as hash from the user name. */
202 candidate
= UID_CLAMP_INTO_RANGE ( siphash24 ( name
, strlen ( name
), hash_key
));
204 ( void ) mkdir ( "/run/systemd/dynamic-uid" , 0755 );
207 char lock_path
[ strlen ( "/run/systemd/dynamic-uid/" ) + DECIMAL_STR_MAX ( uid_t
) + 1 ];
208 _cleanup_close_
int lock_fd
= - 1 ;
211 if (-- n_tries
<= 0 ) /* Give up retrying eventually */
214 if ( candidate
< UID_PICK_MIN
|| candidate
> UID_PICK_MAX
)
217 xsprintf ( lock_path
, "/run/systemd/dynamic-uid/" UID_FMT
, candidate
);
222 lock_fd
= open ( lock_path
, O_CREAT
| O_RDWR
| O_NOFOLLOW
| O_CLOEXEC
| O_NOCTTY
, 0600 );
226 r
= flock ( lock_fd
, LOCK_EX
| LOCK_NB
); /* Try to get a BSD file lock on the UID lock file */
228 if ( errno
== EBUSY
|| errno
== EAGAIN
)
229 goto next
; /* already in use */
234 if ( fstat ( lock_fd
, & st
) < 0 )
239 /* Oh, bummer, we got got the lock, but the file was unlinked between the time we opened it and
240 * got the lock. Close it, and try again. */
241 lock_fd
= safe_close ( lock_fd
);
244 /* Some superficial check whether this UID/GID might already be taken by some static user */
245 if ( getpwuid ( candidate
) || getgrgid (( gid_t
) candidate
)) {
246 ( void ) unlink ( lock_path
);
250 /* Let's store the user name in the lock file, so that we can use it for looking up the username for a UID */
253 { . iov_base
= ( char *) name
, . iov_len
= strlen ( name
) },
254 { . iov_base
= ( char [ 1 ]) { ' \n ' }, . iov_len
= 1 }
257 ( void ) unlink ( lock_path
);
261 ( void ) ftruncate ( lock_fd
, l
);
262 ( void ) make_uid_symlinks ( candidate
, name
, true ); /* also add direct lookup symlinks */
264 * ret_uid
= candidate
;
271 /* Pick another random UID, and see if that works for us. */
272 random_bytes (& candidate
, sizeof ( candidate
));
273 candidate
= UID_CLAMP_INTO_RANGE ( candidate
);
277 static int dynamic_user_pop ( DynamicUser
* d
, uid_t
* ret_uid
, int * ret_lock_fd
) {
278 uid_t uid
= UID_INVALID
;
281 . iov_len
= sizeof ( uid
),
284 struct cmsghdr cmsghdr
;
285 uint8_t buf
[ CMSG_SPACE ( sizeof ( int ))];
288 . msg_control
= & control
,
289 . msg_controllen
= sizeof ( control
),
293 struct cmsghdr
* cmsg
;
302 /* Read the UID and lock fd that is stored in the storage AF_UNIX socket. This should be called with the lock
303 * on the socket taken. */
305 k
= recvmsg ( d
-> storage_socket
[ 0 ], & mh
, MSG_DONTWAIT
| MSG_NOSIGNAL
| MSG_CMSG_CLOEXEC
);
309 cmsg
= cmsg_find (& mh
, SOL_SOCKET
, SCM_RIGHTS
, CMSG_LEN ( sizeof ( int )));
311 lock_fd
= *( int *) CMSG_DATA ( cmsg
);
313 cmsg_close_all (& mh
); /* just in case... */
316 * ret_lock_fd
= lock_fd
;
321 static int dynamic_user_push ( DynamicUser
* d
, uid_t uid
, int lock_fd
) {
324 . iov_len
= sizeof ( uid
),
327 struct cmsghdr cmsghdr
;
328 uint8_t buf
[ CMSG_SPACE ( sizeof ( int ))];
331 . msg_control
= & control
,
332 . msg_controllen
= sizeof ( control
),
340 /* Store the UID and lock_fd in the storage socket. This should be called with the socket pair lock taken. */
343 struct cmsghdr
* cmsg
;
345 cmsg
= CMSG_FIRSTHDR (& mh
);
346 cmsg
-> cmsg_level
= SOL_SOCKET
;
347 cmsg
-> cmsg_type
= SCM_RIGHTS
;
348 cmsg
-> cmsg_len
= CMSG_LEN ( sizeof ( int ));
349 memcpy ( CMSG_DATA ( cmsg
), & lock_fd
, sizeof ( int ));
351 mh
. msg_controllen
= CMSG_SPACE ( sizeof ( int ));
353 mh
. msg_control
= NULL
;
354 mh
. msg_controllen
= 0 ;
357 k
= sendmsg ( d
-> storage_socket
[ 1 ], & mh
, MSG_DONTWAIT
| MSG_NOSIGNAL
);
364 static void unlink_uid_lock ( int lock_fd
, uid_t uid
, const char * name
) {
365 char lock_path
[ strlen ( "/run/systemd/dynamic-uid/" ) + DECIMAL_STR_MAX ( uid_t
) + 1 ];
370 xsprintf ( lock_path
, "/run/systemd/dynamic-uid/" UID_FMT
, uid
);
371 ( void ) unlink ( lock_path
);
373 ( void ) make_uid_symlinks ( uid
, name
, false ); /* remove direct lookup symlinks */
376 int dynamic_user_realize ( DynamicUser
* d
, uid_t
* ret
) {
378 _cleanup_close_
int etc_passwd_lock_fd
= - 1 , uid_lock_fd
= - 1 ;
379 uid_t uid
= UID_INVALID
;
384 /* Acquire a UID for the user name. This will allocate a UID for the user name if the user doesn't exist
385 * yet. If it already exists its existing UID/GID will be reused. */
387 if ( lockf ( d
-> storage_socket
[ 0 ], F_LOCK
, 0 ) < 0 )
390 r
= dynamic_user_pop ( d
, & uid
, & uid_lock_fd
);
398 /* OK, nothing stored yet, let's try to find something useful. While we are working on this release the
399 * lock however, so that nobody else blocks on our NSS lookups. */
400 ( void ) lockf ( d
-> storage_socket
[ 0 ], F_ULOCK
, 0 );
402 /* Let's see if a proper, static user or group by this name exists. Try to take the lock on
403 * /etc/passwd, if that fails with EROFS then /etc is read-only. In that case it's fine if we don't
404 * take the lock, given that users can't be added there anyway in this case. */
405 etc_passwd_lock_fd
= take_etc_passwd_lock ( NULL
);
406 if ( etc_passwd_lock_fd
< 0 && etc_passwd_lock_fd
!= - EROFS
)
407 return etc_passwd_lock_fd
;
409 /* First, let's parse this as numeric UID */
410 r
= parse_uid ( d
-> name
, & uid
);
415 /* OK, this is not a numeric UID. Let's see if there's a user by this name */
416 p
= getpwnam ( d
-> name
);
420 /* Let's see if there's a group by this name */
421 g
= getgrnam ( d
-> name
);
423 /* If the UID/GID of the user/group of the same don't match, refuse operation */
424 if ( uid
!= UID_INVALID
&& uid
!= ( uid_t
) g
-> gr_gid
)
427 uid
= ( uid_t
) g
-> gr_gid
;
431 if ( uid
== UID_INVALID
) {
432 /* No static UID assigned yet, excellent. Let's pick a new dynamic one, and lock it. */
434 uid_lock_fd
= pick_uid ( d
-> name
, & uid
);
439 /* So, we found a working UID/lock combination. Let's see if we actually still need it. */
440 if ( lockf ( d
-> storage_socket
[ 0 ], F_LOCK
, 0 ) < 0 ) {
441 unlink_uid_lock ( uid_lock_fd
, uid
, d
-> name
);
445 r
= dynamic_user_pop ( d
, & new_uid
, & new_uid_lock_fd
);
448 /* OK, something bad happened, let's get rid of the bits we acquired. */
449 unlink_uid_lock ( uid_lock_fd
, uid
, d
-> name
);
453 /* Great! Nothing is stored here, still. Store our newly acquired data. */
455 /* Hmm, so as it appears there's now something stored in the storage socket. Throw away what we
456 * acquired, and use what's stored now. */
458 unlink_uid_lock ( uid_lock_fd
, uid
, d
-> name
);
459 safe_close ( uid_lock_fd
);
462 uid_lock_fd
= new_uid_lock_fd
;
466 /* If the UID/GID was already allocated dynamically, push the data we popped out back in. If it was already
467 * allocated statically, push the UID back too, but do not push the lock fd in. If we allocated the UID
468 * dynamically right here, push that in along with the lock fd for it. */
469 r
= dynamic_user_push ( d
, uid
, uid_lock_fd
);
477 ( void ) lockf ( d
-> storage_socket
[ 0 ], F_ULOCK
, 0 );
481 int dynamic_user_current ( DynamicUser
* d
, uid_t
* ret
) {
482 _cleanup_close_
int lock_fd
= - 1 ;
489 /* Get the currently assigned UID for the user, if there's any. This simply pops the data from the storage socket, and pushes it back in right-away. */
491 if ( lockf ( d
-> storage_socket
[ 0 ], F_LOCK
, 0 ) < 0 )
494 r
= dynamic_user_pop ( d
, & uid
, & lock_fd
);
498 r
= dynamic_user_push ( d
, uid
, lock_fd
);
506 ( void ) lockf ( d
-> storage_socket
[ 0 ], F_ULOCK
, 0 );
510 DynamicUser
* dynamic_user_ref ( DynamicUser
* d
) {
514 assert ( d
-> n_ref
> 0 );
520 DynamicUser
* dynamic_user_unref ( DynamicUser
* d
) {
524 /* Note that this doesn't actually release any resources itself. If a dynamic user should be fully destroyed
525 * and its UID released, use dynamic_user_destroy() instead. NB: the dynamic user table may contain entries
526 * with no references, which is commonly the case right before a daemon reload. */
528 assert ( d
-> n_ref
> 0 );
534 static int dynamic_user_close ( DynamicUser
* d
) {
535 _cleanup_close_
int lock_fd
= - 1 ;
539 /* Release the user ID, by releasing the lock on it, and emptying the storage socket. After this the user is
540 * unrealized again, much like it was after it the DynamicUser object was first allocated. */
542 if ( lockf ( d
-> storage_socket
[ 0 ], F_LOCK
, 0 ) < 0 )
545 r
= dynamic_user_pop ( d
, & uid
, & lock_fd
);
547 /* User wasn't realized yet, nothing to do. */
554 /* This dynamic user was realized and dynamically allocated. In this case, let's remove the lock file. */
555 unlink_uid_lock ( lock_fd
, uid
, d
-> name
);
559 ( void ) lockf ( d
-> storage_socket
[ 0 ], F_ULOCK
, 0 );
563 DynamicUser
* dynamic_user_destroy ( DynamicUser
* d
) {
567 /* Drop a reference to a DynamicUser object, and destroy the user completely if this was the last
568 * reference. This is called whenever a service is shut down and wants its dynamic UID gone. Note that
569 * dynamic_user_unref() is what is called whenever a service is simply freed, for example during a reload
570 * cycle, where the dynamic users should not be destroyed, but our datastructures should. */
572 dynamic_user_unref ( d
);
577 ( void ) dynamic_user_close ( d
);
578 return dynamic_user_free ( d
);
581 int dynamic_user_serialize ( Manager
* m
, FILE * f
, FDSet
* fds
) {
589 /* Dump the dynamic user database into the manager serialization, to deal with daemon reloads. */
591 HASHMAP_FOREACH ( d
, m
-> dynamic_users
, i
) {
594 copy0
= fdset_put_dup ( fds
, d
-> storage_socket
[ 0 ]);
598 copy1
= fdset_put_dup ( fds
, d
-> storage_socket
[ 1 ]);
602 fprintf ( f
, "dynamic-user=%s %i %i \n " , d
-> name
, copy0
, copy1
);
608 void dynamic_user_deserialize_one ( Manager
* m
, const char * value
, FDSet
* fds
) {
609 _cleanup_free_
char * name
= NULL
, * s0
= NULL
, * s1
= NULL
;
616 /* Parse the serialization again, after a daemon reload */
618 r
= extract_many_words (& value
, NULL
, 0 , & name
, & s0
, & s1
, NULL
);
619 if ( r
!= 3 || ! isempty ( value
)) {
620 log_debug ( "Unable to parse dynamic user line." );
624 if ( safe_atoi ( s0
, & fd0
) < 0 || ! fdset_contains ( fds
, fd0
)) {
625 log_debug ( "Unable to process dynamic user fd specification." );
629 if ( safe_atoi ( s1
, & fd1
) < 0 || ! fdset_contains ( fds
, fd1
)) {
630 log_debug ( "Unable to process dynamic user fd specification." );
634 r
= dynamic_user_add ( m
, name
, ( int []) { fd0
, fd1
}, NULL
);
636 log_debug_errno ( r
, "Failed to add dynamic user: %m" );
640 ( void ) fdset_remove ( fds
, fd0
);
641 ( void ) fdset_remove ( fds
, fd1
);
644 void dynamic_user_vacuum ( Manager
* m
, bool close_user
) {
650 /* Empty the dynamic user database, optionally cleaning up orphaned dynamic users, i.e. destroy and free users
651 * to which no reference exist. This is called after a daemon reload finished, in order to destroy users which
652 * might not be referenced anymore. */
654 HASHMAP_FOREACH ( d
, m
-> dynamic_users
, i
) {
659 log_debug ( "Removing orphaned dynamic user %s" , d
-> name
);
660 ( void ) dynamic_user_close ( d
);
663 dynamic_user_free ( d
);
667 int dynamic_user_lookup_uid ( Manager
* m
, uid_t uid
, char ** ret
) {
668 char lock_path
[ strlen ( "/run/systemd/dynamic-uid/" ) + DECIMAL_STR_MAX ( uid_t
) + 1 ];
669 _cleanup_free_
char * user
= NULL
;
676 /* A friendly way to translate a dynamic user's UID into a his name. */
678 if ( uid
< UID_PICK_MIN
)
680 if ( uid
> UID_PICK_MAX
)
683 xsprintf ( lock_path
, "/run/systemd/dynamic-uid/" UID_FMT
, uid
);
684 r
= read_one_line_file ( lock_path
, & user
);
690 /* The lock file might be stale, hence let's verify the data before we return it */
691 r
= dynamic_user_lookup_name ( m
, user
, & check_uid
);
694 if ( check_uid
!= uid
) /* lock file doesn't match our own idea */
703 int dynamic_user_lookup_name ( Manager
* m
, const char * name
, uid_t
* ret
) {
711 /* A friendly call for translating a dynamic user's name into its UID */
713 d
= hashmap_get ( m
-> dynamic_users
, name
);
717 r
= dynamic_user_current ( d
, ret
);
718 if ( r
== - EAGAIN
) /* not realized yet? */
724 int dynamic_creds_acquire ( DynamicCreds
* creds
, Manager
* m
, const char * user
, const char * group
) {
725 bool acquired
= false ;
731 /* A DynamicUser object encapsulates an allocation of both a UID and a GID for a specific name. However, some
732 * services use different user and groups. For cases like that there's DynamicCreds containing a pair of user
733 * and group. This call allocates a pair. */
735 if (! creds
-> user
&& user
) {
736 r
= dynamic_user_acquire ( m
, user
, & creds
-> user
);
745 if ( creds
-> user
&& (! group
|| streq_ptr ( user
, group
)))
746 creds
-> group
= dynamic_user_ref ( creds
-> user
);
748 r
= dynamic_user_acquire ( m
, group
, & creds
-> group
);
751 creds
-> user
= dynamic_user_unref ( creds
-> user
);
760 int dynamic_creds_realize ( DynamicCreds
* creds
, uid_t
* uid
, gid_t
* gid
) {
761 uid_t u
= UID_INVALID
;
762 gid_t g
= GID_INVALID
;
769 /* Realize both the referenced user and group */
772 r
= dynamic_user_realize ( creds
-> user
, & u
);
777 if ( creds
-> group
&& creds
-> group
!= creds
-> user
) {
778 r
= dynamic_user_realize ( creds
-> group
, & g
);
790 void dynamic_creds_unref ( DynamicCreds
* creds
) {
793 creds
-> user
= dynamic_user_unref ( creds
-> user
);
794 creds
-> group
= dynamic_user_unref ( creds
-> group
);
797 void dynamic_creds_destroy ( DynamicCreds
* creds
) {
800 creds
-> user
= dynamic_user_destroy ( creds
-> user
);
801 creds
-> group
= dynamic_user_destroy ( creds
-> group
);