Exemple #1
0
int msg_control_read(struct msg_control *msg_ctrl, struct ancillary *data,
							int minor)
{
	int rc;
	struct msghdr msghdr;
	struct cmsghdr *cmsg = NULL;

#if DEBUG == 1
	static int call_count = 0;
	printf("(uds) [%d] msg_control_read() call_count=%d\n", minor,
							++call_count);
#endif

	data->nfiledes = 0;

	memset(&msghdr, '\0', sizeof(struct msghdr));
	msghdr.msg_control = msg_ctrl->msg_control;
	msghdr.msg_controllen = msg_ctrl->msg_controllen;

	for(cmsg = CMSG_FIRSTHDR(&msghdr); cmsg != NULL;
					cmsg = CMSG_NXTHDR(&msghdr, cmsg)) {

		if (cmsg->cmsg_level == SOL_SOCKET &&
					cmsg->cmsg_type == SCM_RIGHTS) {

			int i;
			int nfds =
				MIN((cmsg->cmsg_len-CMSG_LEN(0))/sizeof(int),
								OPEN_MAX);

			for (i = 0; i < nfds; i++) {
				if (data->nfiledes == OPEN_MAX) {
					return EOVERFLOW;
				}

				data->fds[data->nfiledes] =
					((int *) CMSG_DATA(cmsg))[i];
#if DEBUG == 1
				printf("(uds) [%d] fd[%d]=%d\n", minor,
				data->nfiledes, data->fds[data->nfiledes]);
#endif
				data->nfiledes++;
			}
		}
	}

	/* obtain this socket's credentials */
	rc = getnucred(uds_fd_table[minor].owner, &(data->cred));
	if (rc == -1) {
		return errno;
	}
#if DEBUG == 1
	printf("(uds) [%d] cred={%d,%d,%d}\n", minor,
		data->cred.pid, data->cred.uid,
		data->cred.gid);
#endif
	return OK;
}
Exemple #2
0
int do_getsockopt_peercred_old(message *dev_m_in, message *dev_m_out)
{
	int minor;
	int peer_minor;
	int rc;
	struct ucred cred;
	struct ucred_old cred_old;

#if DEBUG == 1
	static int call_count = 0;
	printf("(uds) [%d] do_getsockopt_peercred() call_count=%d\n",
					uds_minor(dev_m_in), ++call_count);
#endif

	minor = uds_minor(dev_m_in);

	if (uds_fd_table[minor].peer == -1) {

		if (uds_fd_table[minor].err == ECONNRESET) {
			uds_fd_table[minor].err = 0;

			return ECONNRESET;
		} else {
			return ENOTCONN;
		}
	}

	peer_minor = uds_fd_table[minor].peer;

	/* obtain the peer's credentials */
	rc = getnucred(uds_fd_table[peer_minor].owner, &cred);
	if (rc == -1) {
		/* likely error: invalid endpoint / proc doesn't exist */
		return errno;
	}

	/* copy to old structure */
	cred_old.pid = cred.pid;
	cred_old.uid = (short) cred.uid;
	cred_old.gid = (char) cred.gid;

	rc = sys_safecopyto(VFS_PROC_NR, (cp_grant_id_t) dev_m_in->IO_GRANT,
		(vir_bytes) 0, (vir_bytes) &cred_old, sizeof(struct ucred_old),
		D);

	return rc ? EIO : OK;
}
Exemple #3
0
static int hello_open(message *m)
{
    struct ucred new_owner;

    // Sanity check: Don't open in Read/Write mode.
    if (m->COUNT == O_RDWR) {
        fprintf(stderr, "open() was opened in READ_WRITE mode by UID: %d. Bouncing open() request.\n", new_owner.uid);
        return EACCES;
    }

    // Grab the credentials for the new owner.
    if (getnucred(m->USER_ENDPT, &new_owner) != 0) {
        fprintf(stderr, "getnucred failed\n");
        return errno;
    }

    // If empty...
    if (owner == -1) {

        switch (m->COUNT) {

        // WRITE_ONLY mode on an empty secret.
        case O_WRONLY:
            printf("Empty Secret opened in WRITE_ONLY mode by UID: %d\n", new_owner.uid);

            // Set the owner to be full
            owner = new_owner.uid;

            printf("Open file descriptors: %d\n", ++open_file_descriptors);
            
            return OK;

        // READ_ONLY mode on an empty Secret.
        case O_RDONLY:
            fprintf(stderr, "UID %d opened an Empty Secret in READ_ONLY mode.\n", new_owner.uid);

            printf("Open file descriptors: %d\n", ++open_file_descriptors);

            // do nothing.
            return OK;
        // Error state.
        default:
            fprintf(stderr, "unknown open() flags: %d", m->COUNT);
            return -1;
        }
    } 
    // If full...
    else {
        switch (m->COUNT) {

        // READ_ONLY mode on a full Secret.
        case O_RDONLY:
            

            // If the Secret is being read by the owner...
            if (owner == new_owner.uid) {
                printf("Full Secret opened in READ_ONLY mode by the owner: %d\n", new_owner.uid);

                // Set the Secret to be empty.
                owner = -1;

                // The Secret is now opened for reading
                secret_opened_for_reading = true;

                printf("Open file descriptors: %d\n", ++open_file_descriptors);

                return OK;
            }
            // If the Secret is being read by SOMEONE ELSE...
            else {
                printf("Can't read someone else's secret: Full Secret opened in READ_ONLY mode by %d, even though the owner was %d\n", new_owner.uid, owner);
                return -1;
            }

        // WRITE_ONLY mode on a full Secret.
        case O_WRONLY:
            fprintf(stderr, "No space left on device\n");
            return -1;

        // Error state.
        default:
            fprintf(stderr, "unknown open() flags: %d\n", m->COUNT);
            return -1;
        }
    }

    return OK;
}
Exemple #4
0
PUBLIC int uds_open(message *dev_m_in, message *dev_m_out)
{
	message fs_m_in, fs_m_out;
	struct ucred ucred;
	int rc, i;
	int minor;

#if DEBUG == 1
	static int call_count = 0;
	printf("(uds) [%d] uds_open() call_count=%d\n", uds_minor(dev_m_in),
							++call_count);
	printf("Endpoint: 0x%x\n", dev_m_in->IO_ENDPT);
#endif

	/*
	 * Find a slot in the descriptor table for the new descriptor.
	 * The index of the descriptor in the table will be returned.
	 * Subsequent calls to read/write/close/ioctl/etc will use this
	 * minor number. The minor number must be different from the
	 * the /dev/uds device's minor number (currently 0).
	 */

	minor = -1; /* to trap error */

	for (i = 1; i < NR_FDS; i++) {
		if (uds_fd_table[i].state == UDS_FREE) {
			minor = i;
			break;
		}
	}

	if (minor == -1) {

		/* descriptor table full */
		uds_set_reply(dev_m_out, TASK_REPLY, dev_m_in->IO_ENDPT,
				(cp_grant_id_t) dev_m_in->IO_GRANT, ENFILE);
		return ENFILE;
	}

	/*
	 * We found a slot in uds_fd_table, now initialize the descriptor
	 */

	/* mark this one as 'in use' so that it doesn't get assigned to
	 * another socket
	 */
	uds_fd_table[minor].state = UDS_INUSE;

	/* track the system call we are performing in case it gets cancelled */
	uds_fd_table[minor].call_nr = dev_m_in->m_type;
	uds_fd_table[minor].ioctl = 0;
	uds_fd_table[minor].syscall_done = 0;

	/* set the socket owner */
	uds_fd_table[minor].owner = dev_m_in->IO_ENDPT;
	uds_fd_table[minor].endpoint = dev_m_in->IO_ENDPT;

	/* setup select(2) framework */
	uds_fd_table[minor].selecting = 0;
	uds_fd_table[minor].select_proc = 0;
	uds_fd_table[minor].sel_ops_in = 0;
	uds_fd_table[minor].sel_ops_out = 0;
	uds_fd_table[minor].status_updated = 0;

	/* initialize the data pointer (pos) to the start of the PIPE */
	uds_fd_table[minor].pos = 0;

	/* the PIPE is initially empty */
	uds_fd_table[minor].size = 0;

	/* the default for a new socket is to allow reading and writing.
	 * shutdown(2) will remove one or both flags.
	 */
	uds_fd_table[minor].mode = S_IRUSR|S_IWUSR;

	/* In libc socket(2) sets this to the actual value later with the
	 * NWIOSUDSTYPE ioctl().
	 */
	uds_fd_table[minor].type = -1;

	/* Clear the backlog by setting each entry to -1 */
	for (i = 0; i < UDS_SOMAXCONN; i++) {
		/* initially no connections are pending */
		uds_fd_table[minor].backlog[i] = -1;
	}

	memset(&uds_fd_table[minor].ancillary_data, '\0', sizeof(struct 
								ancillary));
	for (i = 0; i < OPEN_MAX; i++) {
		uds_fd_table[minor].ancillary_data.fds[i] = -1;
	}

	/* default the size to UDS_SOMAXCONN */
	uds_fd_table[minor].backlog_size = UDS_SOMAXCONN;

	/* the socket isn't listening for incoming connections until
	 * listen(2) is called
	 */
	uds_fd_table[minor].listening = 0;

	/* initially the socket is not connected to a peer */
	uds_fd_table[minor].peer = -1;

	/* there isn't a child waiting to be accept(2)'d */
	uds_fd_table[minor].child = -1;

	/* initially the socket is not bound or listening on an address */
	memset(&(uds_fd_table[minor].addr), '\0', sizeof(struct sockaddr_un));
	memset(&(uds_fd_table[minor].source), '\0', sizeof(struct sockaddr_un));
	memset(&(uds_fd_table[minor].target), '\0', sizeof(struct sockaddr_un));

	/* Initially the socket isn't suspended. */
	uds_fd_table[minor].suspended = UDS_NOT_SUSPENDED;

	/* and the socket doesn't have an I/O grant initially */
	uds_fd_table[minor].io_gr = (cp_grant_id_t) 0;

	/* since there is no I/O grant it effectively has no size either */
	uds_fd_table[minor].io_gr_size = 0;

	/* The process isn't suspended so we don't flag it as revivable */
	uds_fd_table[minor].ready_to_revive = 0;

	/* get the effective user id and effective group id from the endpoint */
	/* this is needed in the REQ_NEWNODE request to PFS. */
	rc = getnucred(uds_fd_table[minor].endpoint, &ucred);
	if (rc == -1) {
		/* roll back the changes we made to the descriptor */
		memset(&(uds_fd_table[minor]), '\0', sizeof(uds_fd_t));

		/* likely error: invalid endpoint / proc doesn't exist */
		uds_set_reply(dev_m_out, TASK_REPLY, dev_m_in->IO_ENDPT,
				(cp_grant_id_t) dev_m_in->IO_GRANT, errno);
		return errno;
	}

	/* Prepare Request to the FS side of PFS */

	fs_m_in.m_type = REQ_NEWNODE;
	fs_m_in.REQ_MODE = I_NAMED_PIPE;
	fs_m_in.REQ_DEV = NO_DEV;
	fs_m_in.REQ_UID = ucred.uid;
	fs_m_in.REQ_GID = ucred.gid;

	/* Request a new inode on the pipe file system */

	rc = fs_newnode(&fs_m_in, &fs_m_out);
	if (rc != OK) {
		/* roll back the changes we made to the descriptor */
		memset(&(uds_fd_table[minor]), '\0', sizeof(uds_fd_t));

		/* likely error: get_block() failed */
		uds_set_reply(dev_m_out, TASK_REPLY, dev_m_in->IO_ENDPT,
				(cp_grant_id_t) dev_m_in->IO_GRANT, errno);
		return errno;
	}

	/* Process the response */

	uds_fd_table[minor].inode_nr = fs_m_out.RES_INODE_NR;

	/* prepare the reply */

	uds_fd_table[minor].syscall_done = 1;
	uds_set_reply(dev_m_out, TASK_REPLY, dev_m_in->IO_ENDPT,
			(cp_grant_id_t) dev_m_in->IO_GRANT, minor);
	return minor;
}