示例#1
0
static int ncp_fill_super(struct super_block *sb, void *raw_data, int silent)
{
    struct ncp_mount_data_kernel data;
    struct ncp_server *server;
    struct file *ncp_filp;
    struct inode *root_inode;
    struct inode *sock_inode;
    struct socket *sock;
    int error;
    int default_bufsize;
#ifdef CONFIG_NCPFS_PACKET_SIGNING
    int options;
#endif
    struct ncp_entry_info finfo;

    memset(&data, 0, sizeof(data));
    server = kzalloc(sizeof(struct ncp_server), GFP_KERNEL);
    if (!server)
        return -ENOMEM;
    sb->s_fs_info = server;

    error = -EFAULT;
    if (raw_data == NULL)
        goto out;
    switch (*(int*)raw_data) {
    case NCP_MOUNT_VERSION:
    {
        struct ncp_mount_data* md = (struct ncp_mount_data*)raw_data;

        data.flags = md->flags;
        data.int_flags = NCP_IMOUNT_LOGGEDIN_POSSIBLE;
        data.mounted_uid = md->mounted_uid;
        data.wdog_pid = find_get_pid(md->wdog_pid);
        data.ncp_fd = md->ncp_fd;
        data.time_out = md->time_out;
        data.retry_count = md->retry_count;
        data.uid = md->uid;
        data.gid = md->gid;
        data.file_mode = md->file_mode;
        data.dir_mode = md->dir_mode;
        data.info_fd = -1;
        memcpy(data.mounted_vol, md->mounted_vol,
               NCP_VOLNAME_LEN+1);
    }
    break;
    case NCP_MOUNT_VERSION_V4:
    {
        struct ncp_mount_data_v4* md = (struct ncp_mount_data_v4*)raw_data;

        data.flags = md->flags;
        data.mounted_uid = md->mounted_uid;
        data.wdog_pid = find_get_pid(md->wdog_pid);
        data.ncp_fd = md->ncp_fd;
        data.time_out = md->time_out;
        data.retry_count = md->retry_count;
        data.uid = md->uid;
        data.gid = md->gid;
        data.file_mode = md->file_mode;
        data.dir_mode = md->dir_mode;
        data.info_fd = -1;
    }
    break;
    default:
        error = -ECHRNG;
        if (memcmp(raw_data, "vers", 4) == 0) {
            error = ncp_parse_options(&data, raw_data);
        }
        if (error)
            goto out;
        break;
    }
    error = -EBADF;
    ncp_filp = fget(data.ncp_fd);
    if (!ncp_filp)
        goto out;
    error = -ENOTSOCK;
    sock_inode = ncp_filp->f_path.dentry->d_inode;
    if (!S_ISSOCK(sock_inode->i_mode))
        goto out_fput;
    sock = SOCKET_I(sock_inode);
    if (!sock)
        goto out_fput;

    if (sock->type == SOCK_STREAM)
        default_bufsize = 0xF000;
    else
        default_bufsize = 1024;

    sb->s_flags |= MS_NODIRATIME;	/* probably even noatime */
    sb->s_maxbytes = 0xFFFFFFFFU;
    sb->s_blocksize = 1024;	/* Eh...  Is this correct? */
    sb->s_blocksize_bits = 10;
    sb->s_magic = NCP_SUPER_MAGIC;
    sb->s_op = &ncp_sops;
    sb->s_d_op = &ncp_dentry_operations;
    sb->s_bdi = &server->bdi;

    server = NCP_SBP(sb);
    memset(server, 0, sizeof(*server));

    error = bdi_setup_and_register(&server->bdi, "ncpfs", BDI_CAP_MAP_COPY);
    if (error)
        goto out_fput;

    server->ncp_filp = ncp_filp;
    server->ncp_sock = sock;

    if (data.info_fd != -1) {
        struct socket *info_sock;

        error = -EBADF;
        server->info_filp = fget(data.info_fd);
        if (!server->info_filp)
            goto out_bdi;
        error = -ENOTSOCK;
        sock_inode = server->info_filp->f_path.dentry->d_inode;
        if (!S_ISSOCK(sock_inode->i_mode))
            goto out_fput2;
        info_sock = SOCKET_I(sock_inode);
        if (!info_sock)
            goto out_fput2;
        error = -EBADFD;
        if (info_sock->type != SOCK_STREAM)
            goto out_fput2;
        server->info_sock = info_sock;
    }

    /*	server->lock = 0;	*/
    mutex_init(&server->mutex);
    server->packet = NULL;
    /*	server->buffer_size = 0;	*/
    /*	server->conn_status = 0;	*/
    /*	server->root_dentry = NULL;	*/
    /*	server->root_setuped = 0;	*/
    mutex_init(&server->root_setup_lock);
#ifdef CONFIG_NCPFS_PACKET_SIGNING
    /*	server->sign_wanted = 0;	*/
    /*	server->sign_active = 0;	*/
#endif
    init_rwsem(&server->auth_rwsem);
    server->auth.auth_type = NCP_AUTH_NONE;
    /*	server->auth.object_name_len = 0;	*/
    /*	server->auth.object_name = NULL;	*/
    /*	server->auth.object_type = 0;		*/
    /*	server->priv.len = 0;			*/
    /*	server->priv.data = NULL;		*/

    server->m = data;
    /* Although anything producing this is buggy, it happens
       now because of PATH_MAX changes.. */
    if (server->m.time_out < 1) {
        server->m.time_out = 10;
        printk(KERN_INFO "You need to recompile your ncpfs utils..\n");
    }
    server->m.time_out = server->m.time_out * HZ / 100;
    server->m.file_mode = (server->m.file_mode & S_IRWXUGO) | S_IFREG;
    server->m.dir_mode = (server->m.dir_mode & S_IRWXUGO) | S_IFDIR;

#ifdef CONFIG_NCPFS_NLS
    /* load the default NLS charsets */
    server->nls_vol = load_nls_default();
    server->nls_io = load_nls_default();
#endif /* CONFIG_NCPFS_NLS */

    atomic_set(&server->dentry_ttl, 0);	/* no caching */

    INIT_LIST_HEAD(&server->tx.requests);
    mutex_init(&server->rcv.creq_mutex);
    server->tx.creq		= NULL;
    server->rcv.creq	= NULL;

    init_timer(&server->timeout_tm);
#undef NCP_PACKET_SIZE
#define NCP_PACKET_SIZE 131072
    error = -ENOMEM;
    server->packet_size = NCP_PACKET_SIZE;
    server->packet = vmalloc(NCP_PACKET_SIZE);
    if (server->packet == NULL)
        goto out_nls;
    server->txbuf = vmalloc(NCP_PACKET_SIZE);
    if (server->txbuf == NULL)
        goto out_packet;
    server->rxbuf = vmalloc(NCP_PACKET_SIZE);
    if (server->rxbuf == NULL)
        goto out_txbuf;

    lock_sock(sock->sk);
    server->data_ready	= sock->sk->sk_data_ready;
    server->write_space	= sock->sk->sk_write_space;
    server->error_report	= sock->sk->sk_error_report;
    sock->sk->sk_user_data	= server;
    sock->sk->sk_data_ready	  = ncp_tcp_data_ready;
    sock->sk->sk_error_report = ncp_tcp_error_report;
    if (sock->type == SOCK_STREAM) {
        server->rcv.ptr = (unsigned char*)&server->rcv.buf;
        server->rcv.len = 10;
        server->rcv.state = 0;
        INIT_WORK(&server->rcv.tq, ncp_tcp_rcv_proc);
        INIT_WORK(&server->tx.tq, ncp_tcp_tx_proc);
        sock->sk->sk_write_space = ncp_tcp_write_space;
    } else {
        INIT_WORK(&server->rcv.tq, ncpdgram_rcv_proc);
        INIT_WORK(&server->timeout_tq, ncpdgram_timeout_proc);
        server->timeout_tm.data = (unsigned long)server;
        server->timeout_tm.function = ncpdgram_timeout_call;
    }
    release_sock(sock->sk);

    ncp_lock_server(server);
    error = ncp_connect(server);
    ncp_unlock_server(server);
    if (error < 0)
        goto out_rxbuf;
    DPRINTK("ncp_fill_super: NCP_SBP(sb) = %x\n", (int) NCP_SBP(sb));

    error = -EMSGSIZE;	/* -EREMOTESIDEINCOMPATIBLE */
#ifdef CONFIG_NCPFS_PACKET_SIGNING
    if (ncp_negotiate_size_and_options(server, default_bufsize,
                                       NCP_DEFAULT_OPTIONS, &(server->buffer_size), &options) == 0)
    {
        if (options != NCP_DEFAULT_OPTIONS)
        {
            if (ncp_negotiate_size_and_options(server,
                                               default_bufsize,
                                               options & 2,
                                               &(server->buffer_size), &options) != 0)

            {
                goto out_disconnect;
            }
        }
        ncp_lock_server(server);
        if (options & 2)
            server->sign_wanted = 1;
        ncp_unlock_server(server);
    }
    else
#endif	/* CONFIG_NCPFS_PACKET_SIGNING */
        if (ncp_negotiate_buffersize(server, default_bufsize,
                                     &(server->buffer_size)) != 0)
            goto out_disconnect;
    DPRINTK("ncpfs: bufsize = %d\n", server->buffer_size);

    memset(&finfo, 0, sizeof(finfo));
    finfo.i.attributes	= aDIR;
    finfo.i.dataStreamSize	= 0;	/* ignored */
    finfo.i.dirEntNum	= 0;
    finfo.i.DosDirNum	= 0;
#ifdef CONFIG_NCPFS_SMALLDOS
    finfo.i.NSCreator	= NW_NS_DOS;
#endif
    finfo.volume		= NCP_NUMBER_OF_VOLUMES;
    /* set dates of mountpoint to Jan 1, 1986; 00:00 */
    finfo.i.creationTime	= finfo.i.modifyTime
                              = cpu_to_le16(0x0000);
    finfo.i.creationDate	= finfo.i.modifyDate
                              = finfo.i.lastAccessDate
                                = cpu_to_le16(0x0C21);
    finfo.i.nameLen		= 0;
    finfo.i.entryName[0]	= '\0';

    finfo.opened		= 0;
    finfo.ino		= 2;	/* tradition */

    server->name_space[finfo.volume] = NW_NS_DOS;

    error = -ENOMEM;
    root_inode = ncp_iget(sb, &finfo);
    if (!root_inode)
        goto out_disconnect;
    DPRINTK("ncp_fill_super: root vol=%d\n", NCP_FINFO(root_inode)->volNumber);
    sb->s_root = d_alloc_root(root_inode);
    if (!sb->s_root)
        goto out_no_root;
    return 0;

out_no_root:
    iput(root_inode);
out_disconnect:
    ncp_lock_server(server);
    ncp_disconnect(server);
    ncp_unlock_server(server);
out_rxbuf:
    ncp_stop_tasks(server);
    vfree(server->rxbuf);
out_txbuf:
    vfree(server->txbuf);
out_packet:
    vfree(server->packet);
out_nls:
#ifdef CONFIG_NCPFS_NLS
    unload_nls(server->nls_io);
    unload_nls(server->nls_vol);
#endif
    mutex_destroy(&server->rcv.creq_mutex);
    mutex_destroy(&server->root_setup_lock);
    mutex_destroy(&server->mutex);
out_fput2:
    if (server->info_filp)
        fput(server->info_filp);
out_bdi:
    bdi_destroy(&server->bdi);
out_fput:
    /* 23/12/1998 Marcin Dalecki <*****@*****.**>:
     *
     * The previously used put_filp(ncp_filp); was bogus, since
     * it doesn't perform proper unlocking.
     */
    fput(ncp_filp);
out:
    put_pid(data.wdog_pid);
    sb->s_fs_info = NULL;
    kfree(server);
    return error;
}
示例#2
0
static void delayed_put_pid(struct rcu_head *rhp)
{
	struct pid *pid = container_of(rhp, struct pid, rcu);
	put_pid(pid);
}
示例#3
0
static int ncp_parse_options(struct ncp_mount_data_kernel *data, char *options) {
    int optval;
    char *optarg;
    unsigned long optint;
    int version = 0;
    int ret;

    data->flags = 0;
    data->int_flags = 0;
    data->mounted_uid = 0;
    data->wdog_pid = NULL;
    data->ncp_fd = ~0;
    data->time_out = NCP_DEFAULT_TIME_OUT;
    data->retry_count = NCP_DEFAULT_RETRY_COUNT;
    data->uid = 0;
    data->gid = 0;
    data->file_mode = NCP_DEFAULT_FILE_MODE;
    data->dir_mode = NCP_DEFAULT_DIR_MODE;
    data->info_fd = -1;
    data->mounted_vol[0] = 0;

    while ((optval = ncp_getopt("ncpfs", &options, ncp_opts, NULL, &optarg, &optint)) != 0) {
        ret = optval;
        if (ret < 0)
            goto err;
        switch (optval) {
        case 'u':
            data->uid = optint;
            break;
        case 'g':
            data->gid = optint;
            break;
        case 'o':
            data->mounted_uid = optint;
            break;
        case 'm':
            data->file_mode = optint;
            break;
        case 'd':
            data->dir_mode = optint;
            break;
        case 't':
            data->time_out = optint;
            break;
        case 'r':
            data->retry_count = optint;
            break;
        case 'f':
            data->flags = optint;
            break;
        case 'w':
            data->wdog_pid = find_get_pid(optint);
            break;
        case 'n':
            data->ncp_fd = optint;
            break;
        case 'i':
            data->info_fd = optint;
            break;
        case 'v':
            ret = -ECHRNG;
            if (optint < NCP_MOUNT_VERSION_V4)
                goto err;
            if (optint > NCP_MOUNT_VERSION_V5)
                goto err;
            version = optint;
            break;

        }
    }
    return 0;
err:
    put_pid(data->wdog_pid);
    data->wdog_pid = NULL;
    return ret;
}
示例#4
0
static void taskmonitor_exit(void)
{
        if(target_pid)
                put_pid(target_pid);
	pr_info("Goodbye, cruel world\n");
}
示例#5
0
/*
 *  Ok, this is the main fork-routine.
 *
 * It copies the process, and if successful kick-starts
 * it and waits for it to finish using the VM if required.
 */
long do_fork(unsigned long clone_flags,
	      unsigned long stack_start,
	      unsigned long stack_size,
	      int __user *parent_tidptr,
	      int __user *child_tidptr)
{
	struct task_struct *p;
	int trace = 0;
	long nr;

	/*
	 * Do some preliminary argument and permissions checking before we
	 * actually start allocating stuff
	 */
	if (clone_flags & (CLONE_NEWUSER | CLONE_NEWPID)) {
		if (clone_flags & (CLONE_THREAD|CLONE_PARENT))
			return -EINVAL;
	}

	/*
	 * Determine whether and which event to report to ptracer.  When
	 * called from kernel_thread or CLONE_UNTRACED is explicitly
	 * requested, no event is reported; otherwise, report if the event
	 * for the type of forking is enabled.
	 */
	if (!(clone_flags & CLONE_UNTRACED)) {
		if (clone_flags & CLONE_VFORK)
			trace = PTRACE_EVENT_VFORK;
		else if ((clone_flags & CSIGNAL) != SIGCHLD)
			trace = PTRACE_EVENT_CLONE;
		else
			trace = PTRACE_EVENT_FORK;

		if (likely(!ptrace_event_enabled(current, trace)))
			trace = 0;
	}

	p = copy_process(clone_flags, stack_start, stack_size,
			 child_tidptr, NULL, trace);
	/*
	 * Do this prior waking up the new thread - the thread pointer
	 * might get invalid after that point, if the thread exits quickly.
	 */
	if (!IS_ERR(p)) {
		struct completion vfork;
		struct pid *pid;

		trace_sched_process_fork(current, p);

		pid = get_task_pid(p, PIDTYPE_PID);
		nr = pid_vnr(pid);

		if (clone_flags & CLONE_PARENT_SETTID)
			put_user(nr, parent_tidptr);

		if (clone_flags & CLONE_VFORK) {
			p->vfork_done = &vfork;
			init_completion(&vfork);
			get_task_struct(p);
		}

		wake_up_new_task(p);

		/* forking complete and child started to run, tell ptracer */
		if (unlikely(trace))
			ptrace_event_pid(trace, pid);

		if (clone_flags & CLONE_VFORK) {
			if (!wait_for_vfork_done(p, &vfork))
				ptrace_event_pid(PTRACE_EVENT_VFORK_DONE, pid);
		}

		put_pid(pid);
	} else {
		nr = PTR_ERR(p);
	}
	return nr;
}
示例#6
0
void debug_rt_mutex_free_waiter(struct rt_mutex_waiter *waiter)
{
	put_pid(waiter->deadlock_task_pid);
	memset(waiter, 0x22, sizeof(*waiter));
}
示例#7
0
int
uu_lock(const char *tty_name)
{
	int fd, tmpfd, i;
	pid_t pid, pid_old;
	char lckname[PATH_MAX],
	     lcktmpname[PATH_MAX];
	int err, uuerr;

	pid = getpid();
	(void)snprintf(lcktmpname, sizeof(lcktmpname), _PATH_UUCPLOCK LOCKTMP,
			pid);
	(void)snprintf(lckname, sizeof(lckname), _PATH_UUCPLOCK LOCKFMT,
			tty_name);
	if ((tmpfd = creat(lcktmpname, 0664)) < 0)
		GORET(0, UU_LOCK_CREAT_ERR);

	for (i = 0; i < MAXTRIES; i++) {
		if (link (lcktmpname, lckname) < 0) {
			if (errno != EEXIST)
				GORET(1, UU_LOCK_LINK_ERR);
			/*
			 * file is already locked
			 * check to see if the process holding the lock
			 * still exists
			 */
			if ((fd = open(lckname, O_RDONLY)) < 0)
				GORET(1, UU_LOCK_OPEN_ERR);

			if ((pid_old = get_pid (fd, &err)) == -1)
				GORET(2, UU_LOCK_READ_ERR);

			close(fd);

			if (kill(pid_old, 0) == 0 || errno != ESRCH)
				GORET(1, UU_LOCK_INUSE);
			/*
			 * The process that locked the file isn't running, so
			 * we'll lock it ourselves
			 */
			(void)unlink(lckname);
		} else {
			if (!put_pid (tmpfd, pid))
				GORET(3, UU_LOCK_WRITE_ERR);
			break;
		}
	}
	GORET(1, (i >= MAXTRIES) ? UU_LOCK_TRY_ERR : UU_LOCK_OK);

ret3:
	(void)unlink(lckname);
	goto ret1;
ret2:
	(void)close(fd);
ret1:
	(void)close(tmpfd);
	(void)unlink(lcktmpname);
ret0:
	errno = err;
	return uuerr;
}