Beispiel #1
0
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
}