int pipe_stat(struct pipe *cpipe, void *ub, int isstat64) { #if CONFIG_MACF int error; #endif int pipe_size = 0; int pipe_count; struct stat *sb = (struct stat *)0; /* warning avoidance ; protected by isstat64 */ struct stat64 * sb64 = (struct stat64 *)0; /* warning avoidance ; protected by isstat64 */ if (cpipe == NULL) return (EBADF); PIPE_LOCK(cpipe); #if CONFIG_MACF error = mac_pipe_check_stat(kauth_cred_get(), cpipe); if (error) { PIPE_UNLOCK(cpipe); return (error); } #endif if (cpipe->pipe_buffer.buffer == 0) { /* must be stat'ing the write fd */ if (cpipe->pipe_peer) { /* the peer still exists, use it's info */ pipe_size = MAX_PIPESIZE(cpipe->pipe_peer); pipe_count = cpipe->pipe_peer->pipe_buffer.cnt; } else { pipe_count = 0; } } else { pipe_size = MAX_PIPESIZE(cpipe); pipe_count = cpipe->pipe_buffer.cnt; } /* * since peer's buffer is setup ouside of lock * we might catch it in transient state */ if (pipe_size == 0) pipe_size = MAX(PIPE_SIZE, pipesize_blocks[0]); if (isstat64 != 0) { sb64 = (struct stat64 *)ub; bzero(sb64, sizeof(*sb64)); sb64->st_mode = S_IFIFO | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP; sb64->st_blksize = pipe_size; sb64->st_size = pipe_count; sb64->st_blocks = (sb64->st_size + sb64->st_blksize - 1) / sb64->st_blksize; sb64->st_uid = kauth_getuid(); sb64->st_gid = kauth_getgid(); sb64->st_atimespec.tv_sec = cpipe->st_atimespec.tv_sec; sb64->st_atimespec.tv_nsec = cpipe->st_atimespec.tv_nsec; sb64->st_mtimespec.tv_sec = cpipe->st_mtimespec.tv_sec; sb64->st_mtimespec.tv_nsec = cpipe->st_mtimespec.tv_nsec; sb64->st_ctimespec.tv_sec = cpipe->st_ctimespec.tv_sec; sb64->st_ctimespec.tv_nsec = cpipe->st_ctimespec.tv_nsec; /* * Return a relatively unique inode number based on the current * address of this pipe's struct pipe. This number may be recycled * relatively quickly. */ sb64->st_ino = (ino64_t)VM_KERNEL_ADDRPERM((uintptr_t)cpipe); } else { sb = (struct stat *)ub; bzero(sb, sizeof(*sb)); sb->st_mode = S_IFIFO | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP; sb->st_blksize = pipe_size; sb->st_size = pipe_count; sb->st_blocks = (sb->st_size + sb->st_blksize - 1) / sb->st_blksize; sb->st_uid = kauth_getuid(); sb->st_gid = kauth_getgid(); sb->st_atimespec.tv_sec = cpipe->st_atimespec.tv_sec; sb->st_atimespec.tv_nsec = cpipe->st_atimespec.tv_nsec; sb->st_mtimespec.tv_sec = cpipe->st_mtimespec.tv_sec; sb->st_mtimespec.tv_nsec = cpipe->st_mtimespec.tv_nsec; sb->st_ctimespec.tv_sec = cpipe->st_ctimespec.tv_sec; sb->st_ctimespec.tv_nsec = cpipe->st_ctimespec.tv_nsec; /* * Return a relatively unique inode number based on the current * address of this pipe's struct pipe. This number may be recycled * relatively quickly. */ sb->st_ino = (ino_t)VM_KERNEL_ADDRPERM((uintptr_t)cpipe); } PIPE_UNLOCK(cpipe); /* * POSIX: Left as 0: st_dev, st_nlink, st_rdev, st_flags, st_gen, * st_uid, st_gid. * * XXX (st_dev) should be unique, but there is no device driver that * XXX is associated with pipes, since they are implemented via a * XXX struct fileops indirection rather than as FS objects. */ return (0); }
static int new_proc_listener ( kauth_cred_t cred, struct vnode *vp, struct vnode *scriptvp, struct label *vnodelabel, struct label *scriptlabel, struct label *execlabel, struct componentname *cnp, u_int *csflags, void *macpolicyattr, size_t macpolicyattrlen ) #endif { #ifdef _USE_KAUTH vnode_t prog = (vnode_t)arg0; const char* file_path = (const char*)arg1; #else int pathLen = sizeof( g_processes[ 0 ].path ); #endif pid_t pid = 0; pid_t ppid = 0; uid_t uid = 0; #ifdef _USE_KAUTH if( KAUTH_FILEOP_EXEC != action || ( NULL != prog && VREG != vnode_vtype( prog ) ) ) { return KAUTH_RESULT_DEFER; } #endif uid = kauth_getuid(); pid = proc_selfpid(); ppid = proc_selfppid(); // We skip a known false positive if( 0 == ppid && 1 == pid ) { #ifdef _USE_KAUTH return KAUTH_RESULT_DEFER; #else return 0; // Always allow #endif } if( NULL != file_path ) { // rpal_debug_info( "!!!!!! process start: %d/%d/%d %s", ppid, pid, uid, file_path ); } rpal_mutex_lock( g_collector_1_mutex ); #ifdef _USE_KAUTH if( NULL != file_path ) { strncpy( g_processes[ g_nextProcess ].path, file_path, sizeof( g_processes[ g_nextProcess ].path ) - 1 ); } #else vn_getpath( vp, g_processes[ g_nextProcess ].path, &pathLen ); #endif g_processes[ g_nextProcess ].pid = pid; g_processes[ g_nextProcess ].ppid = ppid; g_processes[ g_nextProcess ].uid = uid; g_processes[ g_nextProcess ].ts = rpal_time_getLocal(); g_nextProcess++; if( g_nextProcess == _NUM_BUFFERED_PROCESSES ) { g_nextProcess = 0; rpal_debug_warning( "overflow of the execution buffer" ); } // rpal_debug_info( "now %d processes in buffer", g_nextProcess ); rpal_mutex_unlock( g_collector_1_mutex ); #ifdef _USE_KAUTH return KAUTH_RESULT_DEFER; #else return 0; // Always allow #endif }