libproc - process control library
The /proc interface provides access to the state of each user-level process and thread also known as lightweight process or lwp in the system. It also provides the ability to control such processes and threads. It is a low-level interface.
The libproc library provides a higher-level interface to the features of the /proc interface as well as access to information such as symbol tables which is necessary for the examination and control of processes and threads. For more information, see the proc(5) man page.
A controlling process using libproc can perform the following functions:
Grab a victim process, suspending its execution.
Examine the state of a victim process.
Examine and modify the address space of the victim process.
Make the victim process execute system calls on behalf of the controlling process.
Release the victim process to run again unmolested.
Similarly, a controlling process using libproc can create a controlled victim process in order to control it from the moment of creation.
A controlling process can also grab a core file for post-mortem inspection. However, it cannot cause the dead process to execute anything.
In short, libproc provides all the mechanisms needed by a breakpoint debugger to do its job, but also facilitates the creation of simple one-shot controlling applications to do simple things to victim processes without them being aware of the intrusion.
For example, there is nothing in the /proc interface that exposes a file creation mask of a victim process. However, libproc provides an interface, pr_umask(), that will force a victim process to execute the umask() system call on behalf of a controlling process. For more information, see umask(2).
Here is an example program to do that. (It could be improved; it is pared down to essentials for demonstration purposes.)
#include <stdio.h> #include <string.h> #include <libproc.h> static void __NORETURN usage(const char *command) { (void) fprintf(stderr, "usage:\t%s [-m mask] pid ...\n" " default: report the file creation mask of each process\n" " -m: set the file creation mask of each process to mask\n", command); exit(2); } int main(int argc, char **argv) { char *command = argv[0]; int exitcode = 0; int mflag = 0; mode_t mask; int opt; while ((opt = getopt(argc, argv, "m:")) != EOF) { if (opt != 'm') usage(command); mflag = 1; mask = (mode_t)strtol(optarg, NULL, 8) & 0777; } argc -= optind; argv += optind; if (argc <= 0) usage(command); while (--argc >= 0) { pid_t pid = (pid_t)atoi(*argv++); ps_prochandle_t *Pr; mode_t omask; int gret; if ((Pr = Pgrab(pid, 0, &gret)) == NULL) { (void) fprintf(stderr, "%s: cannot examine %d: %s\n", command, (int)pid, Pgrab_error(gret)); exitcode = 1; } else { if (mflag) omask = pr_umask(Pr, mask); else (void) pr_umask(Pr, omask = pr_umask(Pr, 0)); Prelease(Pr, 0); if (mflag) (void) printf("%d:\t0%3.3o (was 0%3.3o)\n", (int)pid, (int)mask, (int)omask); else (void) printf("%d:\t0%3.3o\n", (int)pid, (int)omask); } } return (exitcode); }
#include <stdio.h> #include <string.h> #include <libproc.h> static void __NORETURN usage(const char *command) { (void) fprintf(stderr, "usage:\t%s [-m mask] pid ...\n" " default: report the file creation mask of each process\n" " -m: set the file creation mask of each process to mask\n", command); exit(2); } int main(int argc, char **argv) { char *command = argv[0]; int exitcode = 0; int mflag = 0; mode_t mask; int opt; while ((opt = getopt(argc, argv, "m:")) != EOF) { if (opt != 'm') usage(command); mflag = 1; mask = (mode_t)strtol(optarg, NULL, 8) & 0777; } argc -= optind; argv += optind; if (argc <= 0) usage(command); while (--argc >= 0) { pid_t pid = (pid_t)atoi(*argv++); ps_prochandle_t *Pr; mode_t omask; int gret; if ((Pr = Pgrab(pid, 0, &gret)) == NULL) { (void) fprintf(stderr, "%s: cannot examine %d: %s\n", command, (int)pid, Pgrab_error(gret)); exitcode = 1; } else { if (mflag) omask = pr_umask(Pr, mask); else (void) pr_umask(Pr, omask = pr_umask(Pr, 0)); Prelease(Pr, 0); if (mflag) (void) printf("%d:\t0%3.3o (was 0%3.3o)\n", (int)pid, (int)mask, (int)omask); else (void) printf("%d:\t0%3.3o\n", (int)pid, (int)omask); } } return (exitcode); }
libproc currently provides the following functions to cause a victim process to execute the corresponding system calls on behalf of a controlling process. More such interfaces may be added in the future.
pr_access() pr_chmod() pr_chown() pr_close() pr_door_info() pr_exit() pr_faccessat() pr_fchmod() pr_fchmodat() pr_fchown() pr_fchownat() pr_fcntl() pr_fstat() pr_fstat64() pr_fstatat() pr_fstatat64() pr_fstatvfs() pr_fstatvfs64() pr_futimens() pr_getitimer() pr_getpeername() pr_getpeerucred() pr_getrlimit() pr_getrlimit64() pr_getsockname() pr_getsockopt() pr_getzoneid() pr_ioctl() pr_lchown() pr_link() pr_linkat() pr_llseek() pr_lseek() pr_lstat() pr_lstat64() pr_memcntl() pr_meminfo() pr_mkdir() pr_mkdirat() pr_mkfifo() pr_mkfifoat() pr_mknod() pr_mknodat() pr_mmap() pr_munmap() pr_open() pr_open64() pr_openat() pr_openat64() pr_readlink() pr_readlinkat() pr_rename() pr_renameat() pr_rmdir() pr_setitimer() pr_setrlimit() pr_setrlimit64() pr_sigaction() pr_stat() pr_stat64() pr_statvfs() pr_statvfs64() pr_symlink() pr_symlinkat() pr_umask() pr_unlink() pr_unlinkat() pr_utimensat() pr_waitid()
The shared object libproc.so.1 provides the public interfaces listed below. See the individual manual pages in section 3PROC for their descriptions. For additional information about shared object interfaces, see the intro(3) man page.
Lclearfault() Lclearsig() Lctlfd() Ldstop() Lfree() Lgetareg() Lgrab() Lgrab_error() Lprochandle() Lpsinfo() Lputareg() Lrefresh() Lsetrun() Lstate() Lstatus() Lstop() Lsync() Lwait() Lxecbkpt() Lxecwapt() Paction() Paddr_to_loadobj() Paddr_to_map() Paddr_to_text_map() Pasfd() Pbrandname() Pclearfault() Pclearsig() Pcontent() Pcreate() Pcreate_agent() Pcreate_error() Pcred() Pctlfd() Pdelbkpt() Pdelwapt() Pdestroy_agent() Pdirfd() Pdstop() Penv_iter() Pexecname() Pfault() Pfdinfolist() Pfgcore() Pfgrab_core() Pfree() Pgcore() Pgetareg() Pgetauxval() Pgetauxvec() Pgetenv() Pgrab() Pgrab_core() Pgrab_error() Pgrab_file() Pisprocdir() Plookup_by_addr() Plookup_by_name() Plwp_alt_stack() Plwp_getfpregs() Plwp_getpsinfo() Plwp_getregs() Plwp_getstatus() Plwp_getxregs() Plwp_iter() Plwp_iter_all() Plwp_main_stack() Plwp_setfpregs() Plwp_setregs() Plwp_setxregs() Plwp_stack() Pmapping_iter() Pname_to_loadobj() Pname_to_map() Pnsig() Pobject_iter() Pobjname() Pplatform() Ppriv() Ppsinfo() Pputareg() Prd_agent() Pread() Pread_string() Prefresh() Prelease() Preopen() Preset_maps() Psetbkpt() Psetcred() Psetfault() Psetflags() Psetpriv() Psetrun() Psetsignal() Psetsysentry() Psetsysexit() Psetwapt() Psetzoneid() Psignal() Pstack_iter() Pstate() Pstatus() Pstop() Psymbol_iter() Psymbol_iter_by_addr() Psymbol_iter_by_name() Psync() Psyscall() Psysentry() Psysexit() Puname() Punsetflags() Pupdate_maps() Pwait() Pwrite() Pxecbkpt() Pxecwapt() Pzonename() Pzonepath() Pzoneroot() pr_access() pr_chmod() pr_chown() pr_close() pr_door_info() pr_exit() pr_faccessat() pr_fchmod() pr_fchmodat() pr_fchown() pr_fchownat() pr_fcntl() pr_fstat() pr_fstat64() pr_fstatat() pr_fstatat64() pr_fstatvfs() pr_fstatvfs64() pr_futimens() pr_getitimer() pr_getpeername() pr_getpeerucred() pr_getrlimit() pr_getrlimit64() pr_getsockname() pr_getsockopt() pr_getzoneid() pr_ioctl() pr_lchown() pr_link() pr_linkat() pr_llseek() pr_lseek() pr_lstat() pr_lstat64() pr_memcntl() pr_meminfo() pr_mkdir() pr_mkdirat() pr_mkfifo() pr_mkfifoat() pr_mknod() pr_mknodat() pr_mmap() pr_munmap() pr_open() pr_open64() pr_openat() pr_openat64() pr_readlink() pr_readlinkat() pr_rename() pr_renameat() pr_rmdir() pr_setitimer() pr_setrlimit() pr_setrlimit64() pr_sigaction() pr_stat() pr_stat64() pr_statvfs() pr_statvfs64() pr_symlink() pr_symlinkat() pr_umask() pr_unlink() pr_unlinkat() pr_utimensat() pr_waitid() proc_arg_grab() proc_arg_psinfo() proc_content2str() proc_finistdio() proc_fltname() proc_flushstdio() proc_get_psinfo() proc_initstdio() proc_lwp_in_set() proc_lwp_range_valid() proc_signame() proc_str2content() proc_str2flt() proc_str2sig() proc_str2sys() proc_sysname() proc_unctrl_psinfo() proc_walk()
The following interface is unique to the x86 version of libproc:
Pldt()
The following interfaces are unique to the SPARC version of libproc:
Plwp_getasrs() Plwp_getgwindows() Plwp_setasrs()
32-bit shared object
64-bit shared object
See attributes(7) for descriptions of the following attributes:
|
proc(1), truss(1), umask(2), intro(3), libproc.h(3HEAD), proc(5), attributes(7)
All programs linked with libproc should be compiled in 64-bit mode because 32-bit /proc tools cannot examine 64-bit processes, but 64-bit /proc tools can examine and control both 32-bit and 64-bit processes.
A program compiled in 32-bit mode and linked with libproc cannot be compiled in the large file compilation environment. Such programs can however use the transitional compilation environment.
Because the interfaces provided by libproc are intended for the control of other processes, they are unsafe to be used by more than one thread at a time on any one victim process unless the controlling process implements the necessary mutual exclusion protocol. Their use in signal handlers is deprecated.