2017-11-18 17:09:20 +01:00
/* SPDX-License-Identifier: LGPL-2.1+ */
2015-04-10 19:10:00 +02:00
2016-06-14 23:52:29 +02:00
# include <sched.h>
# include <sys/mount.h>
2016-02-22 18:36:54 +01:00
# include <sys/personality.h>
2016-06-14 23:52:29 +02:00
# include <sys/prctl.h>
2015-04-10 19:10:00 +02:00
# include <sys/stat.h>
2015-10-24 22:58:24 +02:00
# include <sys/types.h>
2015-04-10 19:10:00 +02:00
# include <sys/wait.h>
# include <unistd.h>
2017-10-03 10:41:51 +02:00
# if HAVE_VALGRIND_VALGRIND_H
2016-06-19 23:43:35 +00:00
# include <valgrind/valgrind.h>
# endif
2015-04-10 19:10:00 +02:00
2015-10-27 03:01:06 +01:00
# include "alloc-util.h"
2016-02-22 18:36:54 +01:00
# include "architecture.h"
2016-06-14 23:52:29 +02:00
# include "fd-util.h"
2015-04-10 19:10:00 +02:00
# include "log.h"
# include "macro.h"
2016-06-12 19:51:11 -04:00
# include "parse-util.h"
2015-10-24 22:58:24 +02:00
# include "process-util.h"
2017-12-22 13:08:14 +01:00
# include "signal-util.h"
2016-06-12 19:42:51 -04:00
# include "stdio-util.h"
2015-10-24 22:58:24 +02:00
# include "string-util.h"
2015-04-10 23:15:59 +02:00
# include "terminal-util.h"
2016-07-27 14:22:26 -07:00
# include "test-helper.h"
2018-09-13 14:31:13 +02:00
# include "tests.h"
2015-10-24 22:58:24 +02:00
# include "util.h"
# include "virt.h"
2015-04-10 19:10:00 +02:00
2016-06-12 19:42:51 -04:00
static void test_get_process_comm ( pid_t pid ) {
2015-04-10 19:10:00 +02:00
struct stat st ;
2016-07-18 22:31:34 +02:00
_cleanup_free_ char * a = NULL , * c = NULL , * d = NULL , * f = NULL , * i = NULL ;
2015-04-10 19:10:00 +02:00
_cleanup_free_ char * env = NULL ;
2017-12-14 19:02:29 +01:00
char path [ STRLEN ( " /proc//comm " ) + DECIMAL_STR_MAX ( pid_t ) ] ;
2015-04-10 19:10:00 +02:00
pid_t e ;
uid_t u ;
gid_t g ;
dev_t h ;
int r ;
2016-06-12 19:42:51 -04:00
xsprintf ( path , " /proc/ " PID_FMT " /comm " , pid ) ;
if ( stat ( path , & st ) = = 0 ) {
assert_se ( get_process_comm ( pid , & a ) > = 0 ) ;
log_info ( " PID " PID_FMT " comm: '%s' " , pid , a ) ;
2015-04-29 21:40:54 +02:00
} else
2016-06-12 19:42:51 -04:00
log_warning ( " %s not exist. " , path ) ;
2015-04-10 19:10:00 +02:00
2016-06-12 19:42:51 -04:00
assert_se ( get_process_cmdline ( pid , 0 , true , & c ) > = 0 ) ;
log_info ( " PID " PID_FMT " cmdline: '%s' " , pid , c ) ;
2015-04-10 19:10:00 +02:00
2016-06-12 19:42:51 -04:00
assert_se ( get_process_cmdline ( pid , 8 , false , & d ) > = 0 ) ;
2016-06-14 23:52:29 +02:00
log_info ( " PID " PID_FMT " cmdline truncated to 8: '%s' " , pid , d ) ;
free ( d ) ;
assert_se ( get_process_cmdline ( pid , 1 , false , & d ) > = 0 ) ;
log_info ( " PID " PID_FMT " cmdline truncated to 1: '%s' " , pid , d ) ;
2015-04-10 19:10:00 +02:00
2016-06-12 19:42:51 -04:00
assert_se ( get_process_ppid ( pid , & e ) > = 0 ) ;
log_info ( " PID " PID_FMT " PPID: " PID_FMT , pid , e ) ;
assert_se ( pid = = 1 ? e = = 0 : e > 0 ) ;
2015-04-10 19:10:00 +02:00
2016-06-12 19:42:51 -04:00
assert_se ( is_kernel_thread ( pid ) = = 0 | | pid ! = 1 ) ;
2015-04-10 19:10:00 +02:00
2016-06-12 19:42:51 -04:00
r = get_process_exe ( pid , & f ) ;
2015-04-10 19:10:00 +02:00
assert_se ( r > = 0 | | r = = - EACCES ) ;
2016-06-12 19:42:51 -04:00
log_info ( " PID " PID_FMT " exe: '%s' " , pid , strna ( f ) ) ;
2015-04-10 19:10:00 +02:00
2016-06-12 19:42:51 -04:00
assert_se ( get_process_uid ( pid , & u ) = = 0 ) ;
log_info ( " PID " PID_FMT " UID: " UID_FMT , pid , u ) ;
assert_se ( u = = 0 | | pid ! = 1 ) ;
2015-04-10 19:10:00 +02:00
2016-06-12 19:42:51 -04:00
assert_se ( get_process_gid ( pid , & g ) = = 0 ) ;
log_info ( " PID " PID_FMT " GID: " GID_FMT , pid , g ) ;
assert_se ( g = = 0 | | pid ! = 1 ) ;
2015-04-10 19:10:00 +02:00
2016-06-12 19:42:51 -04:00
r = get_process_environ ( pid , & env ) ;
2015-04-10 19:10:00 +02:00
assert_se ( r > = 0 | | r = = - EACCES ) ;
2016-06-12 19:42:51 -04:00
log_info ( " PID " PID_FMT " strlen(environ): %zi " , pid , env ? ( ssize_t ) strlen ( env ) : ( ssize_t ) - errno ) ;
2015-04-10 19:10:00 +02:00
2015-09-07 13:42:47 +02:00
if ( ! detect_container ( ) )
2016-06-12 19:42:51 -04:00
assert_se ( get_ctty_devnr ( pid , & h ) = = - ENXIO | | pid ! = 1 ) ;
2015-04-10 19:10:00 +02:00
2018-02-16 07:03:13 +01:00
( void ) getenv_for_pid ( pid , " PATH " , & i ) ;
2016-06-12 19:42:51 -04:00
log_info ( " PID " PID_FMT " $PATH: '%s' " , pid , strna ( i ) ) ;
2015-04-10 19:10:00 +02:00
}
2018-05-16 21:50:35 -04:00
static void test_get_process_comm_escape_one ( const char * input , const char * output ) {
_cleanup_free_ char * n = NULL ;
log_info ( " input: <%s> — output: <%s> " , input , output ) ;
assert_se ( prctl ( PR_SET_NAME , input ) > = 0 ) ;
assert_se ( get_process_comm ( 0 , & n ) > = 0 ) ;
log_info ( " got: <%s> " , n ) ;
assert_se ( streq_ptr ( n , output ) ) ;
}
static void test_get_process_comm_escape ( void ) {
_cleanup_free_ char * saved = NULL ;
assert_se ( get_process_comm ( 0 , & saved ) > = 0 ) ;
test_get_process_comm_escape_one ( " " , " " ) ;
test_get_process_comm_escape_one ( " foo " , " foo " ) ;
test_get_process_comm_escape_one ( " 012345678901234 " , " 012345678901234 " ) ;
test_get_process_comm_escape_one ( " 0123456789012345 " , " 012345678901234 " ) ;
test_get_process_comm_escape_one ( " äöüß " , " \\ 303 \\ 244 \\ 303… " ) ;
test_get_process_comm_escape_one ( " xäöüß " , " x \\ 303 \\ 244… " ) ;
test_get_process_comm_escape_one ( " xxäöüß " , " xx \\ 303 \\ 244… " ) ;
test_get_process_comm_escape_one ( " xxxäöüß " , " xxx \\ 303 \\ 244… " ) ;
test_get_process_comm_escape_one ( " xxxxäöüß " , " xxxx \\ 303 \\ 244… " ) ;
test_get_process_comm_escape_one ( " xxxxxäöüß " , " xxxxx \\ 303… " ) ;
assert_se ( prctl ( PR_SET_NAME , saved ) > = 0 ) ;
}
2015-04-10 19:10:00 +02:00
static void test_pid_is_unwaited ( void ) {
pid_t pid ;
pid = fork ( ) ;
assert_se ( pid > = 0 ) ;
if ( pid = = 0 ) {
_exit ( EXIT_SUCCESS ) ;
} else {
int status ;
waitpid ( pid , & status , 0 ) ;
assert_se ( ! pid_is_unwaited ( pid ) ) ;
}
2017-07-20 16:19:18 +02:00
assert_se ( pid_is_unwaited ( getpid_cached ( ) ) ) ;
2015-04-10 19:10:00 +02:00
assert_se ( ! pid_is_unwaited ( - 1 ) ) ;
}
static void test_pid_is_alive ( void ) {
pid_t pid ;
pid = fork ( ) ;
assert_se ( pid > = 0 ) ;
if ( pid = = 0 ) {
_exit ( EXIT_SUCCESS ) ;
} else {
int status ;
waitpid ( pid , & status , 0 ) ;
assert_se ( ! pid_is_alive ( pid ) ) ;
}
2017-07-20 16:19:18 +02:00
assert_se ( pid_is_alive ( getpid_cached ( ) ) ) ;
2015-04-10 19:10:00 +02:00
assert_se ( ! pid_is_alive ( - 1 ) ) ;
}
2016-02-22 18:36:54 +01:00
static void test_personality ( void ) {
assert_se ( personality_to_string ( PER_LINUX ) ) ;
assert_se ( ! personality_to_string ( PERSONALITY_INVALID ) ) ;
assert_se ( streq ( personality_to_string ( PER_LINUX ) , architecture_to_string ( native_architecture ( ) ) ) ) ;
assert_se ( personality_from_string ( personality_to_string ( PER_LINUX ) ) = = PER_LINUX ) ;
assert_se ( personality_from_string ( architecture_to_string ( native_architecture ( ) ) ) = = PER_LINUX ) ;
# ifdef __x86_64__
assert_se ( streq_ptr ( personality_to_string ( PER_LINUX ) , " x86-64 " ) ) ;
assert_se ( streq_ptr ( personality_to_string ( PER_LINUX32 ) , " x86 " ) ) ;
assert_se ( personality_from_string ( " x86-64 " ) = = PER_LINUX ) ;
assert_se ( personality_from_string ( " x86 " ) = = PER_LINUX32 ) ;
assert_se ( personality_from_string ( " ia64 " ) = = PERSONALITY_INVALID ) ;
assert_se ( personality_from_string ( NULL ) = = PERSONALITY_INVALID ) ;
assert_se ( personality_from_string ( personality_to_string ( PER_LINUX32 ) ) = = PER_LINUX32 ) ;
# endif
}
2016-06-14 23:52:29 +02:00
static void test_get_process_cmdline_harder ( void ) {
char path [ ] = " /tmp/test-cmdlineXXXXXX " ;
_cleanup_close_ int fd = - 1 ;
_cleanup_free_ char * line = NULL ;
pid_t pid ;
if ( geteuid ( ) ! = 0 )
return ;
2017-10-03 10:41:51 +02:00
# if HAVE_VALGRIND_VALGRIND_H
2016-06-19 23:43:35 +00:00
/* valgrind patches open(/proc//cmdline)
* so , test_get_process_cmdline_harder fails always
* See https : //github.com/systemd/systemd/pull/3555#issuecomment-226564908 */
if ( RUNNING_ON_VALGRIND )
return ;
# endif
2016-06-14 23:52:29 +02:00
pid = fork ( ) ;
if ( pid > 0 ) {
siginfo_t si ;
( void ) wait_for_terminate ( pid , & si ) ;
assert_se ( si . si_code = = CLD_EXITED ) ;
assert_se ( si . si_status = = 0 ) ;
return ;
}
assert_se ( pid = = 0 ) ;
assert_se ( unshare ( CLONE_NEWNS ) > = 0 ) ;
2018-07-19 10:24:07 +00:00
if ( mount ( NULL , " / " , NULL , MS_SLAVE | MS_REC , NULL ) < 0 ) {
log_warning_errno ( errno , " mount(..., \" / \" , MS_SLAVE|MS_REC, ...) failed: %m " ) ;
assert_se ( IN_SET ( errno , EPERM , EACCES ) ) ;
return ;
}
2018-03-09 01:10:42 +00:00
2016-06-14 23:52:29 +02:00
fd = mkostemp ( path , O_CLOEXEC ) ;
assert_se ( fd > = 0 ) ;
2016-11-17 20:57:22 -05:00
2018-07-19 10:24:07 +00:00
/* Note that we don't unmount the following bind-mount at the end of the test because the kernel
* will clear up its / proc / PID / hierarchy automatically as soon as the test stops . */
2016-11-17 20:57:22 -05:00
if ( mount ( path , " /proc/self/cmdline " , " bind " , MS_BIND , NULL ) < 0 ) {
/* This happens under selinux… Abort the test in this case. */
log_warning_errno ( errno , " mount(..., \" /proc/self/cmdline \" , \" bind \" , ...) failed: %m " ) ;
2018-07-19 10:24:07 +00:00
assert_se ( IN_SET ( errno , EPERM , EACCES ) ) ;
2016-11-17 20:57:22 -05:00
return ;
}
2016-06-14 23:52:29 +02:00
assert_se ( unlink ( path ) > = 0 ) ;
assert_se ( prctl ( PR_SET_NAME , " testa " ) > = 0 ) ;
2017-07-20 16:19:18 +02:00
assert_se ( get_process_cmdline ( getpid_cached ( ) , 0 , false , & line ) = = - ENOENT ) ;
2016-06-14 23:52:29 +02:00
2017-07-20 16:19:18 +02:00
assert_se ( get_process_cmdline ( getpid_cached ( ) , 0 , true , & line ) > = 0 ) ;
2016-06-14 23:52:29 +02:00
assert_se ( streq ( line , " [testa] " ) ) ;
line = mfree ( line ) ;
2017-07-20 16:19:18 +02:00
assert_se ( get_process_cmdline ( getpid_cached ( ) , 1 , true , & line ) > = 0 ) ;
2016-06-14 23:52:29 +02:00
assert_se ( streq ( line , " " ) ) ;
line = mfree ( line ) ;
2017-07-20 16:19:18 +02:00
assert_se ( get_process_cmdline ( getpid_cached ( ) , 2 , true , & line ) > = 0 ) ;
2016-06-14 23:52:29 +02:00
assert_se ( streq ( line , " [ " ) ) ;
line = mfree ( line ) ;
2017-07-20 16:19:18 +02:00
assert_se ( get_process_cmdline ( getpid_cached ( ) , 3 , true , & line ) > = 0 ) ;
2016-06-14 23:52:29 +02:00
assert_se ( streq ( line , " [. " ) ) ;
line = mfree ( line ) ;
2017-07-20 16:19:18 +02:00
assert_se ( get_process_cmdline ( getpid_cached ( ) , 4 , true , & line ) > = 0 ) ;
2016-06-14 23:52:29 +02:00
assert_se ( streq ( line , " [.. " ) ) ;
line = mfree ( line ) ;
2017-07-20 16:19:18 +02:00
assert_se ( get_process_cmdline ( getpid_cached ( ) , 5 , true , & line ) > = 0 ) ;
2016-06-14 23:52:29 +02:00
assert_se ( streq ( line , " [... " ) ) ;
line = mfree ( line ) ;
2017-07-20 16:19:18 +02:00
assert_se ( get_process_cmdline ( getpid_cached ( ) , 6 , true , & line ) > = 0 ) ;
2016-06-14 23:52:29 +02:00
assert_se ( streq ( line , " [...] " ) ) ;
line = mfree ( line ) ;
2017-07-20 16:19:18 +02:00
assert_se ( get_process_cmdline ( getpid_cached ( ) , 7 , true , & line ) > = 0 ) ;
2016-06-14 23:52:29 +02:00
assert_se ( streq ( line , " [t...] " ) ) ;
line = mfree ( line ) ;
2017-07-20 16:19:18 +02:00
assert_se ( get_process_cmdline ( getpid_cached ( ) , 8 , true , & line ) > = 0 ) ;
2016-06-14 23:52:29 +02:00
assert_se ( streq ( line , " [testa] " ) ) ;
line = mfree ( line ) ;
assert_se ( write ( fd , " \0 \0 \0 \0 \0 \0 \0 \0 \0 " , 10 ) = = 10 ) ;
2017-07-20 16:19:18 +02:00
assert_se ( get_process_cmdline ( getpid_cached ( ) , 0 , false , & line ) = = - ENOENT ) ;
2016-06-14 23:52:29 +02:00
2017-07-20 16:19:18 +02:00
assert_se ( get_process_cmdline ( getpid_cached ( ) , 0 , true , & line ) > = 0 ) ;
2016-06-14 23:52:29 +02:00
assert_se ( streq ( line , " [testa] " ) ) ;
line = mfree ( line ) ;
assert_se ( write ( fd , " foo \0 bar \0 \0 \0 \0 \0 " , 10 ) = = 10 ) ;
2017-07-20 16:19:18 +02:00
assert_se ( get_process_cmdline ( getpid_cached ( ) , 0 , false , & line ) > = 0 ) ;
2016-06-14 23:52:29 +02:00
assert_se ( streq ( line , " foo bar " ) ) ;
line = mfree ( line ) ;
2017-07-20 16:19:18 +02:00
assert_se ( get_process_cmdline ( getpid_cached ( ) , 0 , true , & line ) > = 0 ) ;
2016-06-14 23:52:29 +02:00
assert_se ( streq ( line , " foo bar " ) ) ;
line = mfree ( line ) ;
assert_se ( write ( fd , " quux " , 4 ) = = 4 ) ;
2017-07-20 16:19:18 +02:00
assert_se ( get_process_cmdline ( getpid_cached ( ) , 0 , false , & line ) > = 0 ) ;
2016-06-14 23:52:29 +02:00
assert_se ( streq ( line , " foo bar quux " ) ) ;
line = mfree ( line ) ;
2017-07-20 16:19:18 +02:00
assert_se ( get_process_cmdline ( getpid_cached ( ) , 0 , true , & line ) > = 0 ) ;
2016-06-14 23:52:29 +02:00
assert_se ( streq ( line , " foo bar quux " ) ) ;
line = mfree ( line ) ;
2017-07-20 16:19:18 +02:00
assert_se ( get_process_cmdline ( getpid_cached ( ) , 1 , true , & line ) > = 0 ) ;
2016-06-14 23:52:29 +02:00
assert_se ( streq ( line , " " ) ) ;
line = mfree ( line ) ;
2017-07-20 16:19:18 +02:00
assert_se ( get_process_cmdline ( getpid_cached ( ) , 2 , true , & line ) > = 0 ) ;
2016-06-14 23:52:29 +02:00
assert_se ( streq ( line , " . " ) ) ;
line = mfree ( line ) ;
2017-07-20 16:19:18 +02:00
assert_se ( get_process_cmdline ( getpid_cached ( ) , 3 , true , & line ) > = 0 ) ;
2016-06-14 23:52:29 +02:00
assert_se ( streq ( line , " .. " ) ) ;
line = mfree ( line ) ;
2017-07-20 16:19:18 +02:00
assert_se ( get_process_cmdline ( getpid_cached ( ) , 4 , true , & line ) > = 0 ) ;
2016-06-14 23:52:29 +02:00
assert_se ( streq ( line , " ... " ) ) ;
line = mfree ( line ) ;
2017-07-20 16:19:18 +02:00
assert_se ( get_process_cmdline ( getpid_cached ( ) , 5 , true , & line ) > = 0 ) ;
2016-06-14 23:52:29 +02:00
assert_se ( streq ( line , " f... " ) ) ;
line = mfree ( line ) ;
2017-07-20 16:19:18 +02:00
assert_se ( get_process_cmdline ( getpid_cached ( ) , 6 , true , & line ) > = 0 ) ;
2016-06-14 23:52:29 +02:00
assert_se ( streq ( line , " fo... " ) ) ;
line = mfree ( line ) ;
2017-07-20 16:19:18 +02:00
assert_se ( get_process_cmdline ( getpid_cached ( ) , 7 , true , & line ) > = 0 ) ;
2016-06-14 23:52:29 +02:00
assert_se ( streq ( line , " foo... " ) ) ;
line = mfree ( line ) ;
2017-07-20 16:19:18 +02:00
assert_se ( get_process_cmdline ( getpid_cached ( ) , 8 , true , & line ) > = 0 ) ;
2016-06-14 23:52:29 +02:00
assert_se ( streq ( line , " foo... " ) ) ;
line = mfree ( line ) ;
2017-07-20 16:19:18 +02:00
assert_se ( get_process_cmdline ( getpid_cached ( ) , 9 , true , & line ) > = 0 ) ;
2016-06-14 23:52:29 +02:00
assert_se ( streq ( line , " foo b... " ) ) ;
line = mfree ( line ) ;
2017-07-20 16:19:18 +02:00
assert_se ( get_process_cmdline ( getpid_cached ( ) , 10 , true , & line ) > = 0 ) ;
2016-06-14 23:52:29 +02:00
assert_se ( streq ( line , " foo ba... " ) ) ;
line = mfree ( line ) ;
2017-07-20 16:19:18 +02:00
assert_se ( get_process_cmdline ( getpid_cached ( ) , 11 , true , & line ) > = 0 ) ;
2016-06-14 23:52:29 +02:00
assert_se ( streq ( line , " foo bar... " ) ) ;
line = mfree ( line ) ;
2017-07-20 16:19:18 +02:00
assert_se ( get_process_cmdline ( getpid_cached ( ) , 12 , true , & line ) > = 0 ) ;
2016-06-14 23:52:29 +02:00
assert_se ( streq ( line , " foo bar... " ) ) ;
line = mfree ( line ) ;
2017-07-20 16:19:18 +02:00
assert_se ( get_process_cmdline ( getpid_cached ( ) , 13 , true , & line ) > = 0 ) ;
2016-06-14 23:52:29 +02:00
assert_se ( streq ( line , " foo bar quux " ) ) ;
line = mfree ( line ) ;
2017-07-20 16:19:18 +02:00
assert_se ( get_process_cmdline ( getpid_cached ( ) , 14 , true , & line ) > = 0 ) ;
2016-06-14 23:52:29 +02:00
assert_se ( streq ( line , " foo bar quux " ) ) ;
line = mfree ( line ) ;
2017-07-20 16:19:18 +02:00
assert_se ( get_process_cmdline ( getpid_cached ( ) , 1000 , true , & line ) > = 0 ) ;
2016-06-14 23:52:29 +02:00
assert_se ( streq ( line , " foo bar quux " ) ) ;
line = mfree ( line ) ;
assert_se ( ftruncate ( fd , 0 ) > = 0 ) ;
assert_se ( prctl ( PR_SET_NAME , " aaaa bbbb cccc " ) > = 0 ) ;
2017-07-20 16:19:18 +02:00
assert_se ( get_process_cmdline ( getpid_cached ( ) , 0 , false , & line ) = = - ENOENT ) ;
2016-06-14 23:52:29 +02:00
2017-07-20 16:19:18 +02:00
assert_se ( get_process_cmdline ( getpid_cached ( ) , 0 , true , & line ) > = 0 ) ;
2016-06-14 23:52:29 +02:00
assert_se ( streq ( line , " [aaaa bbbb cccc] " ) ) ;
line = mfree ( line ) ;
2017-07-20 16:19:18 +02:00
assert_se ( get_process_cmdline ( getpid_cached ( ) , 10 , true , & line ) > = 0 ) ;
2016-06-14 23:52:29 +02:00
assert_se ( streq ( line , " [aaaa...] " ) ) ;
line = mfree ( line ) ;
2017-07-20 16:19:18 +02:00
assert_se ( get_process_cmdline ( getpid_cached ( ) , 11 , true , & line ) > = 0 ) ;
2016-06-14 23:52:29 +02:00
assert_se ( streq ( line , " [aaaa...] " ) ) ;
line = mfree ( line ) ;
2017-07-20 16:19:18 +02:00
assert_se ( get_process_cmdline ( getpid_cached ( ) , 12 , true , & line ) > = 0 ) ;
2016-06-14 23:52:29 +02:00
assert_se ( streq ( line , " [aaaa b...] " ) ) ;
line = mfree ( line ) ;
safe_close ( fd ) ;
2017-12-22 13:24:40 +01:00
_exit ( EXIT_SUCCESS ) ;
2016-06-14 23:52:29 +02:00
}
2017-08-03 22:31:46 +02:00
static void test_rename_process_now ( const char * p , int ret ) {
2016-12-06 20:29:07 +01:00
_cleanup_free_ char * comm = NULL , * cmdline = NULL ;
int r ;
r = rename_process ( p ) ;
assert_se ( r = = ret | |
( ret = = 0 & & r > = 0 ) | |
( ret > 0 & & r > 0 ) ) ;
if ( r < 0 )
2017-08-03 22:31:46 +02:00
return ;
2016-12-06 20:29:07 +01:00
2017-10-03 10:41:51 +02:00
# if HAVE_VALGRIND_VALGRIND_H
2016-12-06 20:29:07 +01:00
/* see above, valgrind is weird, we can't verify what we are doing here */
if ( RUNNING_ON_VALGRIND )
2017-08-03 22:31:46 +02:00
return ;
2016-12-06 20:29:07 +01:00
# endif
assert_se ( get_process_comm ( 0 , & comm ) > = 0 ) ;
log_info ( " comm = <%s> " , comm ) ;
2018-06-01 21:43:43 +02:00
assert_se ( strneq ( comm , p , TASK_COMM_LEN - 1 ) ) ;
2016-12-06 20:29:07 +01:00
assert_se ( get_process_cmdline ( 0 , 0 , false , & cmdline ) > = 0 ) ;
2017-08-03 22:31:46 +02:00
/* we cannot expect cmdline to be renamed properly without privileges */
if ( geteuid ( ) = = 0 ) {
log_info ( " cmdline = <%s> " , cmdline ) ;
2017-12-14 19:02:29 +01:00
assert_se ( strneq ( p , cmdline , STRLEN ( " test-process-util " ) ) ) ;
2017-08-03 22:31:46 +02:00
assert_se ( startswith ( p , cmdline ) ) ;
} else
log_info ( " cmdline = <%s> (not verified) " , cmdline ) ;
}
static void test_rename_process_one ( const char * p , int ret ) {
siginfo_t si ;
pid_t pid ;
pid = fork ( ) ;
assert_se ( pid > = 0 ) ;
if ( pid = = 0 ) {
/* child */
test_rename_process_now ( p , ret ) ;
_exit ( EXIT_SUCCESS ) ;
}
assert_se ( wait_for_terminate ( pid , & si ) > = 0 ) ;
assert_se ( si . si_code = = CLD_EXITED ) ;
assert_se ( si . si_status = = EXIT_SUCCESS ) ;
}
static void test_rename_process_multi ( void ) {
pid_t pid ;
pid = fork ( ) ;
assert_se ( pid > = 0 ) ;
2016-12-06 20:29:07 +01:00
2017-08-03 22:31:46 +02:00
if ( pid > 0 ) {
siginfo_t si ;
assert_se ( wait_for_terminate ( pid , & si ) > = 0 ) ;
assert_se ( si . si_code = = CLD_EXITED ) ;
assert_se ( si . si_status = = EXIT_SUCCESS ) ;
return ;
}
/* child */
test_rename_process_now ( " one " , 1 ) ;
test_rename_process_now ( " more " , 0 ) ; /* longer than "one", hence truncated */
2017-11-27 21:52:32 +00:00
( void ) setresuid ( 99 , 99 , 99 ) ; /* change uid when running privileged */
2017-08-03 22:31:46 +02:00
test_rename_process_now ( " time! " , 0 ) ;
test_rename_process_now ( " 0 " , 1 ) ; /* shorter than "one", should fit */
test_rename_process_one ( " " , - EINVAL ) ;
test_rename_process_one ( NULL , - EINVAL ) ;
2016-12-06 20:29:07 +01:00
_exit ( EXIT_SUCCESS ) ;
}
static void test_rename_process ( void ) {
test_rename_process_one ( NULL , - EINVAL ) ;
test_rename_process_one ( " " , - EINVAL ) ;
test_rename_process_one ( " foo " , 1 ) ; /* should always fit */
test_rename_process_one ( " this is a really really long process name, followed by some more words " , 0 ) ; /* unlikely to fit */
test_rename_process_one ( " 1234567 " , 1 ) ; /* should always fit */
2017-08-03 22:31:46 +02:00
test_rename_process_multi ( ) ; /* multiple invocations and dropped privileges */
2016-12-06 20:29:07 +01:00
}
2017-07-20 15:46:05 +02:00
static void test_getpid_cached ( void ) {
siginfo_t si ;
pid_t a , b , c , d , e , f , child ;
a = raw_getpid ( ) ;
b = getpid_cached ( ) ;
c = getpid ( ) ;
assert_se ( a = = b & & a = = c ) ;
child = fork ( ) ;
assert_se ( child > = 0 ) ;
if ( child = = 0 ) {
/* In child */
a = raw_getpid ( ) ;
b = getpid_cached ( ) ;
c = getpid ( ) ;
assert_se ( a = = b & & a = = c ) ;
2017-12-22 13:24:40 +01:00
_exit ( EXIT_SUCCESS ) ;
2017-07-20 15:46:05 +02:00
}
d = raw_getpid ( ) ;
e = getpid_cached ( ) ;
f = getpid ( ) ;
assert_se ( a = = d & & a = = e & & a = = f ) ;
assert_se ( wait_for_terminate ( child , & si ) > = 0 ) ;
assert_se ( si . si_status = = 0 ) ;
assert_se ( si . si_code = = CLD_EXITED ) ;
}
# define MEASURE_ITERATIONS (10000000LLU)
static void test_getpid_measure ( void ) {
unsigned long long i ;
usec_t t , q ;
t = now ( CLOCK_MONOTONIC ) ;
for ( i = 0 ; i < MEASURE_ITERATIONS ; i + + )
( void ) getpid ( ) ;
q = now ( CLOCK_MONOTONIC ) - t ;
log_info ( " glibc getpid(): %llu/s \n " , ( unsigned long long ) ( MEASURE_ITERATIONS * USEC_PER_SEC / q ) ) ;
t = now ( CLOCK_MONOTONIC ) ;
for ( i = 0 ; i < MEASURE_ITERATIONS ; i + + )
( void ) getpid_cached ( ) ;
q = now ( CLOCK_MONOTONIC ) - t ;
log_info ( " getpid_cached(): %llu/s \n " , ( unsigned long long ) ( MEASURE_ITERATIONS * USEC_PER_SEC / q ) ) ;
}
2017-12-22 13:08:14 +01:00
static void test_safe_fork ( void ) {
siginfo_t status ;
pid_t pid ;
int r ;
BLOCK_SIGNALS ( SIGCHLD ) ;
r = safe_fork ( " (test-child) " , FORK_RESET_SIGNALS | FORK_CLOSE_ALL_FDS | FORK_DEATHSIG | FORK_NULL_STDIO | FORK_REOPEN_LOG , & pid ) ;
assert_se ( r > = 0 ) ;
if ( r = = 0 ) {
/* child */
usleep ( 100 * USEC_PER_MSEC ) ;
_exit ( 88 ) ;
}
assert_se ( wait_for_terminate ( pid , & status ) > = 0 ) ;
assert_se ( status . si_code = = CLD_EXITED ) ;
assert_se ( status . si_status = = 88 ) ;
}
2018-01-11 16:02:47 +01:00
static void test_pid_to_ptr ( void ) {
assert_se ( PTR_TO_PID ( NULL ) = = 0 ) ;
assert_se ( PID_TO_PTR ( 0 ) = = NULL ) ;
assert_se ( PTR_TO_PID ( PID_TO_PTR ( 1 ) ) = = 1 ) ;
assert_se ( PTR_TO_PID ( PID_TO_PTR ( 2 ) ) = = 2 ) ;
assert_se ( PTR_TO_PID ( PID_TO_PTR ( - 1 ) ) = = - 1 ) ;
assert_se ( PTR_TO_PID ( PID_TO_PTR ( - 2 ) ) = = - 2 ) ;
assert_se ( PTR_TO_PID ( PID_TO_PTR ( INT16_MAX ) ) = = INT16_MAX ) ;
assert_se ( PTR_TO_PID ( PID_TO_PTR ( INT16_MIN ) ) = = INT16_MIN ) ;
# if SIZEOF_PID_T >= 4
assert_se ( PTR_TO_PID ( PID_TO_PTR ( INT32_MAX ) ) = = INT32_MAX ) ;
assert_se ( PTR_TO_PID ( PID_TO_PTR ( INT32_MIN ) ) = = INT32_MIN ) ;
# endif
}
2018-03-16 11:15:58 +01:00
static void test_ioprio_class_from_to_string_one ( const char * val , int expected ) {
assert_se ( ioprio_class_from_string ( val ) = = expected ) ;
if ( expected > = 0 ) {
_cleanup_free_ char * s = NULL ;
unsigned ret ;
assert_se ( ioprio_class_to_string_alloc ( expected , & s ) = = 0 ) ;
/* We sometimes get a class number and sometimes a number back */
assert_se ( streq ( s , val ) | |
safe_atou ( val , & ret ) = = 0 ) ;
}
}
2016-12-06 20:29:07 +01:00
2018-03-16 11:15:58 +01:00
static void test_ioprio_class_from_to_string ( void ) {
test_ioprio_class_from_to_string_one ( " none " , IOPRIO_CLASS_NONE ) ;
test_ioprio_class_from_to_string_one ( " realtime " , IOPRIO_CLASS_RT ) ;
test_ioprio_class_from_to_string_one ( " best-effort " , IOPRIO_CLASS_BE ) ;
test_ioprio_class_from_to_string_one ( " idle " , IOPRIO_CLASS_IDLE ) ;
test_ioprio_class_from_to_string_one ( " 0 " , 0 ) ;
test_ioprio_class_from_to_string_one ( " 1 " , 1 ) ;
test_ioprio_class_from_to_string_one ( " 7 " , 7 ) ;
test_ioprio_class_from_to_string_one ( " 8 " , 8 ) ;
test_ioprio_class_from_to_string_one ( " 9 " , - 1 ) ;
test_ioprio_class_from_to_string_one ( " -1 " , - 1 ) ;
}
int main ( int argc , char * argv [ ] ) {
2018-09-13 14:31:13 +02:00
test_setup_logging ( LOG_DEBUG ) ;
2015-04-10 19:10:00 +02:00
2016-12-06 20:29:07 +01:00
saved_argc = argc ;
saved_argv = argv ;
2016-06-12 19:51:11 -04:00
if ( argc > 1 ) {
pid_t pid = 0 ;
( void ) parse_pid ( argv [ 1 ] , & pid ) ;
test_get_process_comm ( pid ) ;
} else {
2016-07-27 14:22:26 -07:00
TEST_REQ_RUNNING_SYSTEMD ( test_get_process_comm ( 1 ) ) ;
2016-06-12 19:51:11 -04:00
test_get_process_comm ( getpid ( ) ) ;
}
2018-05-16 21:50:35 -04:00
test_get_process_comm_escape ( ) ;
2015-04-10 19:10:00 +02:00
test_pid_is_unwaited ( ) ;
test_pid_is_alive ( ) ;
2016-02-22 18:36:54 +01:00
test_personality ( ) ;
2016-06-14 23:52:29 +02:00
test_get_process_cmdline_harder ( ) ;
2016-12-06 20:29:07 +01:00
test_rename_process ( ) ;
2017-07-20 15:46:05 +02:00
test_getpid_cached ( ) ;
test_getpid_measure ( ) ;
2017-12-22 13:08:14 +01:00
test_safe_fork ( ) ;
2018-01-11 16:02:47 +01:00
test_pid_to_ptr ( ) ;
2018-03-16 11:15:58 +01:00
test_ioprio_class_from_to_string ( ) ;
2015-04-10 19:10:00 +02:00
return 0 ;
}