static void *
v9fs_vfs_follow_link_dotl(struct dentry *dentry, struct nameidata *nd)
{
	int retval;
	struct p9_fid *fid;
	char *link = __getname();
	char *target;

	P9_DPRINTK(P9_DEBUG_VFS, "%s\n", dentry->d_name.name);

	if (!link) {
		link = ERR_PTR(-ENOMEM);
		goto ndset;
	}
	fid = v9fs_fid_lookup(dentry);
	if (IS_ERR(fid)) {
		__putname(link);
		link = ERR_CAST(fid);
		goto ndset;
	}
	retval = p9_client_readlink(fid, &target);
	if (!retval) {
		strcpy(link, target);
		kfree(target);
		goto ndset;
	}
	__putname(link);
	link = ERR_PTR(retval);
ndset:
	nd_set_link(nd, link);
	return NULL;
}
Exemple #2
0
void v9fs_session_close(struct v9fs_session_info *v9ses)
{
	if (v9ses->clnt) {
		p9_client_destroy(v9ses->clnt);
		v9ses->clnt = NULL;
	}

	__putname(v9ses->name);
	__putname(v9ses->remotename);
}
Exemple #3
0
void v9fs_session_close(struct v9fs_session_info *v9ses)
{
    if (v9ses->clnt) {
        p9_client_destroy(v9ses->clnt);
        v9ses->clnt = NULL;
    }

    __putname(v9ses->uname);
    __putname(v9ses->aname);
    kfree(v9ses->options);
}
Exemple #4
0
void v9fs_session_close(struct v9fs_session_info *v9ses)
{
	if (v9ses->mux) {
		v9fs_mux_destroy(v9ses->mux);
		v9ses->mux = NULL;
	}

	if (v9ses->transport) {
		v9ses->transport->close(v9ses->transport);
		kfree(v9ses->transport);
		v9ses->transport = NULL;
	}

	__putname(v9ses->name);
	__putname(v9ses->remotename);
}
static bool fw_get_filesystem_firmware(struct firmware_buf *buf)
{
	int i;
	bool success = false;
	char *path = __getname();

	for (i = 0; i < ARRAY_SIZE(fw_path); i++) {
		struct file *file;

		/* skip the unset customized path */
		if (!fw_path[i][0])
			continue;

		snprintf(path, PATH_MAX, "%s/%s", fw_path[i], buf->fw_id);

		file = filp_open(path, O_RDONLY, 0);
		if (IS_ERR(file))
			continue;
		success = fw_read_file_contents(file, buf);
		fput(file);
		if (success)
			break;
	}
	__putname(path);
	return success;
}
Exemple #6
0
/* Read in a filename from the context file, obtaining memory from __getname */
const char *__cr_getname(cr_errbuf_t *eb, struct file *filp, int null_ok)
{
    char *name;
    int err;

    name = __getname();
    if (!name) {
        CR_ERR_EB(eb, "Couldn't allocate buffer for file name.");
        err = -ENOMEM;
        goto out;
    }

    /* now read out the name */
    err = cr_fgets(eb, name, PATH_MAX, filp);
    if (err < 0) {
        CR_ERR_EB(eb, "Bad read of filename.");
        goto out_free;
    } else if (err == 0) {
	if (!null_ok) err = -EIO;
	goto out_free;
    }

    return name;

out_free:
    __putname(name);
out:
    return (err < 0) ? ERR_PTR(err) : NULL;
}
Exemple #7
0
/* Create a new link to an existing (but potentially unlinked) dentry.
 * If the target link already exists we return the dentry, but if the target
 * exists and is not a link to the desired object, we return -EEXIST.
 *
 * NOTE: We once tried to do this via vfs_link(), rather than sys_link().
 * That was "better" in the sense that it was able to link to unlinked
 * targets (which this cannot).  However, that was not working over NFS
 * for reasons I never did figure out. -PHH
 */
struct dentry *
cr_link(cr_errbuf_t *eb, struct path *old_path, const char *name)
{
    struct nameidata nd;
    char *buf, *old_name;
    struct dentry *new_dentry = NULL;
    int retval;
    mm_segment_t oldfs;
    
    /* Lookup the path to the "old" file.
     * This is the part that prevents us from linking to an unlinked target.
     */
    retval = -ENOMEM;
    buf = __getname();
    if (!buf) goto out;
    old_name = cr_getpath(old_path, buf, PATH_MAX);
    if (IS_ERR(old_name)) {
	retval = PTR_ERR(old_name);
	goto out_free;
    }

    /* Now sys_link() */
    oldfs = get_fs();
    set_fs(KERNEL_DS);
    retval = sys_link(old_name, name);
    set_fs(oldfs);
    if (retval == -EEXIST) {
	/* Keep going, it may be the one we want */
    } else if (retval < 0) {
	CR_ERR_EB(eb, "cr_link: sys_link(%s,%s) returned %d", old_name, name, retval);
	goto out_free;
    }

    /* Now get the dentry for the newly-created object.
     * YES, there is a potential race, but we check below that we have the right object.
     */
    retval = path_lookup(name, LOOKUP_FOLLOW, &nd);
    if (retval < 0) {
	CR_ERR_EB(eb, "cr_link: path_lookup(%s) returned %d", name, retval);
	goto out_free;
    }
    new_dentry = dget(nd.nd_dentry);
    cr_path_release(&nd);

    /* Check that we have a link to the desired object.
     * Needed for sys_link() == -EEXIST and for the link-to-lookup race.
     */
    if (new_dentry->d_inode != old_path->dentry->d_inode) {
	dput(new_dentry);
	retval = -EEXIST;
	goto out_free;
    }

out_free:
    __putname(buf);
out:
    return (retval < 0) ? ERR_PTR(retval) : new_dentry;
}
Exemple #8
0
/*
 * cr_anonymous_rename
 *
 * Rewrite a filename to an anonymous value
 *
 * len is strlen and size is buffer size
 */
static char *
cr_anonymous_rename(cr_errbuf_t *eb, const char *in_buf, unsigned long id)
{
    size_t len;
    char *out_buf, *p;

    len = strlen(in_buf);
    if (len >= PATH_MAX) {
	/* XXX: probably not what we want to do */
	len = PATH_MAX - 1;
    }

    /* strdup() */
    out_buf = __getname();
    if (out_buf == NULL) {
	goto out;
    }
    memcpy(out_buf, in_buf, len+1);

    /* dirname() */
    p = out_buf + len;
    while ((p != out_buf) && (*p != '/')) {
	--p;
    }
    ++p;
    len = p - out_buf;

#if BITS_PER_LONG == 32
    if (len > PATH_MAX - 20) {
	CR_ERR_EB(eb, "cr_anonymous_rename - unlinked name too long for renaming");
	goto out_free;
    }
    sprintf(p, ".blcr_%04x.%08lx", (unsigned int)current->pid, id);
#elif BITS_PER_LONG == 64
    if (len > PATH_MAX - 24) {
	CR_ERR_EB(eb, "cr_anonymous_rename - unlinked name too long for renaming");
	goto out_free;
    }
    sprintf(p, ".blcr_%04x.%016lx", (unsigned int)current->pid, id);
#else
    #error "No value for BITS_PER_LONG"
#endif

    return out_buf;

out_free:
    __putname(out_buf);
out:
    return NULL;
}
Exemple #9
0
/* This function is ONLY designed for SVFS_STATE_DA */
int llfs_create(struct dentry *dentry)
{
    struct inode *inode = dentry->d_inode;
    struct svfs_inode *si = SVFS_I(inode);
    struct svfs_datastore *sd;
    struct file *llfs_file;
    char *ref_path;
    int ret;

    sd = svfs_datastore_get(LLFS_TYPE_ANY, 0);
    if (!sd) {
        ret = PTR_ERR(sd);
        goto out;
    }
    si->llfs_md.llfs_type = sd->type;
    si->llfs_md.llfs_fsid = svfs_datastore_fsid(sd->pathname);
    ret = -ENOMEM;
    ref_path = __getname();
    if (!ref_path)
        goto out;
    ret = svfs_backing_store_get_path2(SVFS_SB(inode->i_sb),
                                       SVFS_SB(inode->i_sb)->bse + 
                                       inode->i_ino,
                                       si->llfs_md.llfs_pathname,
                                       NAME_MAX - 1);
    if (ret)
        goto out_putname;
    snprintf(ref_path, PATH_MAX - 1, "%s%s", sd->pathname,
             si->llfs_md.llfs_pathname);
    svfs_debug(mdc, "New LLFS path %s, state 0x%x\n", ref_path, si->state);
    llfs_file = filp_open(ref_path, O_RDWR | O_CREAT,
                          S_IRUGO | S_IWUSR);
    ret = PTR_ERR(llfs_file);
    if (IS_ERR(llfs_file))
        goto out_putname;
    si->llfs_md.llfs_filp = llfs_file;
    si->state |= SVFS_STATE_CONN;
    si->state &= ~SVFS_STATE_DA;
    ret = 0;
    
out_putname:
    __putname(ref_path);
out:
    svfs_exit(mdc, "err %d. [NOTE]: if you get error here,"
              " you should check the LLFS permissions!\n", ret);
    return ret;
}
static char *sysctl_getname(const int *name, int nlen, const struct bin_table **tablep)
{
	char *tmp, *result;

	result = ERR_PTR(-ENOMEM);
	tmp = __getname();
	if (tmp) {
		const struct bin_table *table = get_sysctl(name, nlen, tmp);
		result = tmp;
		*tablep = table;
		if (IS_ERR(table)) {
			__putname(tmp);
			result = ERR_CAST(table);
		}
	}
	return result;
}
Exemple #11
0
/* Saves pathname, returning bytes written (or <0 on error),
 * NULL dentry yields saved string value of NULL (distinct from empty string).
 * Uses supplied buf, if any, or will alloc/free otherwise.
 */
int cr_save_pathname(cr_errbuf_t *eb, struct file *cr_filp, struct path *path, char *orig_buf, int size)
{
    int retval;
    const char *name = NULL;
    char *buf = orig_buf;

    /* Short cut on NULL path or dentry */
    if (!path || !path->dentry) {
	goto write;
    }

    /* Allocate buf if none was supplied */
    if (!buf) {
        retval = -ENOMEM;
        buf = __getname();
        if (!buf) {
            goto out;
        }
	size = PATH_MAX;
    }

    /* find the file name */
    name = cr_getpath(path, buf, size);
	CR_INFO("file = %s\n");
    if (name == NULL) {
        CR_ERR_EB(eb, "Bad or non/existant name!");
        retval = -EBADF;
        goto out_bad;
    }

    /* now write out the name */
write:
    retval = cr_fputs(eb, name, cr_filp);
    if (retval < 0) {
        CR_ERR_EB(eb, "cr_save_pathname - Bad file write! (cr_fputs returned %d)", retval);
        goto out_bad;
    }

out_bad:
    if (buf && !orig_buf) {
      __putname(buf);
    }
out:
    return retval;
}
Exemple #12
0
static int smb_follow_link(struct dentry *dentry, struct nameidata *nd)
{
	char *link = __getname();
	DEBUG1("followlink of %s/%s\n", DENTRY_PATH(dentry));

	if (!link) {
		link = ERR_PTR(-ENOMEM);
	} else {
		int len = smb_proc_read_link(server_from_dentry(dentry),
						dentry, link, PATH_MAX - 1);
		if (len < 0) {
			__putname(link);
			link = ERR_PTR(len);
		} else {
			link[len] = 0;
		}
	}
	nd_set_link(nd, link);
	return 0;
}
static ssize_t binary_sysctl(const int *name, int nlen,
	void __user *oldval, size_t oldlen, void __user *newval, size_t newlen)
{
	const struct bin_table *table = NULL;
	struct vfsmount *mnt;
	struct file *file;
	ssize_t result;
	char *pathname;
	int flags;

	pathname = sysctl_getname(name, nlen, &table);
	result = PTR_ERR(pathname);
	if (IS_ERR(pathname))
		goto out;

	
	if (oldval && oldlen && newval && newlen) {
		flags = O_RDWR;
	} else if (newval && newlen) {
		flags = O_WRONLY;
	} else if (oldval && oldlen) {
		flags = O_RDONLY;
	} else {
		result = 0;
		goto out_putname;
	}

	mnt = current->nsproxy->pid_ns->proc_mnt;
	file = file_open_root(mnt->mnt_root, mnt, pathname, flags);
	result = PTR_ERR(file);
	if (IS_ERR(file))
		goto out_putname;

	result = table->convert(file, oldval, oldlen, newval, newlen);

	fput(file);
out_putname:
	__putname(pathname);
out:
	return result;
}
Exemple #14
0
/*
 * ima_d_path - return a pointer to the full pathname
 *
 * Attempt to return a pointer to the full pathname for use in the
 * IMA measurement list, IMA audit records, and auditing logs.
 *
 * On failure, return a pointer to a copy of the filename, not dname.
 * Returning a pointer to dname, could result in using the pointer
 * after the memory has been freed.
 */
const char *ima_d_path(const struct path *path, char **pathbuf, char *namebuf)
{
	char *pathname = NULL;

	*pathbuf = __getname();
	if (*pathbuf) {
		pathname = d_absolute_path(path, *pathbuf, PATH_MAX);
		if (IS_ERR(pathname)) {
			__putname(*pathbuf);
			*pathbuf = NULL;
			pathname = NULL;
		}
	}

	if (!pathname) {
		strlcpy(namebuf, path->dentry->d_name.name, NAME_MAX);
		pathname = namebuf;
	}

	return pathname;
}
Exemple #15
0
static bool fw_get_filesystem_firmware(struct device *device,
				       struct firmware_buf *buf,
				       phys_addr_t dest_addr, size_t dest_size)
{
	int i;
	bool success = false;
	char *path = __getname();

	for (i = 0; i < ARRAY_SIZE(fw_path); i++) {
		struct file *file;

		/* skip the unset customized path */
		if (!fw_path[i][0])
			continue;

		snprintf(path, PATH_MAX, "%s/%s", fw_path[i], buf->fw_id);

		file = filp_open(path, O_RDONLY, 0);
		if (IS_ERR(file))
			continue;
		success = fw_read_file_contents(file, buf);
		fput(file);
		filp_close(file, NULL);
		if (success)
			break;
	}
	__putname(path);

	if (success) {
		dev_dbg(device, "firmware: direct-loading firmware %s\n",
			buf->fw_id);
		mutex_lock(&fw_lock);
		set_bit(FW_STATUS_DONE, &buf->status);
		complete_all(&buf->completion);
		mutex_unlock(&fw_lock);
	}

	return success;
}
static int handle_file_write_req(struct rk_baseband *bb, struct ipc_msg *pmsg)
{
    int ret;
    const char* fname;
    loff_t offset;
    void *buf;
    size_t sz;
    char *path = __getname();
    struct file *file;

    /* argv[0] : relative file path */
    /* argv[1] : file offset */
    /* argv[2] : buffer pointer */
    /* argv[3] : length */

    if (IPCMSG_GET_ARGC(pmsg) != 4)
        return -1;

    fname = (const char*)IPCMSG_GET_ARG(pmsg, 0);
    offset = (loff_t)IPCMSG_GET_ARG(pmsg, 1);
    buf = (void*)IPCMSG_GET_ARG(pmsg, 2);
    sz = (size_t)IPCMSG_GET_ARG(pmsg, 3);

    snprintf(path, PATH_MAX, "%s/%s", bb->nv_path, fname);
    file = filp_open(path, O_RDWR, 0);
    if (IS_ERR(file)) {
        return -1;
    }

    ret = vfs_write(file, buf, sz, &offset);

    fput(file);
    __putname(path);

    return ret;
}
Exemple #17
0
Fichier : itb.c Projet : macan/hvfs
struct storage_result *mdsl_read_itb(struct storage_index *si)
{
    struct mmap_window *mw;
    struct storage_result *sr;
    char *path;

    path = __getname();
    if (!mpath) {
        hvfs_err(mdsl, "__getname() failed\n");
        return ERR_PTR(-ENOMEM);
    }
    mpath = sprintf("%s/%d/md", HVFS_HOME, si->sic.uuid);
    /* FIXME: how to get the range max quickly? max range based! */
    mw = find_get_md_memwin(path, MD_RANGE, si->sic.arg0);
    max = *(u64 *)(mw->addr + mw->offset);
    min = *(u64 *)(mw->addr + mw->offset + sizeof(u64));
    put_range_memwin(mw);

    /* FIXME: check whether itbid is in the range (min, max] */
    path = sprintf("%s/%d/range.[%016d]", HVFS_HOME, si->sic.uuid, max);
    /* get the range memory window */
    mw = find_get_range_memwin(path, si->sic.arg0);
    itb_offset = *(u64 *)(mw->addr + mw->offset);
    put_range_memwin(mw);

    /* get the ITB */
    path = sprintf("%s/%d/itb", HVFS_HOME, si->sic.uuid);
    sr = get_free_sr();
    sr->flag = SR_ITB;
    sr->data = get_itb(path, itb_offset, &sr->len);
    if (!sr->data)
        sr->err = -ENOENT;

    __putname(path);
    return sr;
}
Exemple #18
0
static struct dentry *
InodeOpLookup(struct inode *dir,      // IN: parent directory's inode
              struct dentry *dentry,  // IN: dentry to lookup
              struct nameidata *nd)   // IN: lookup intent and information
{
   char *filename;
   struct inode *inode;
   int ret;

   if (!dir || !dentry) {
      Warning("InodeOpLookup: invalid args from kernel\n");
      return ERR_PTR(-EINVAL);
   }

   /* The kernel should only pass us our own inodes, but check just to be safe. */
   if (!INODE_TO_IINFO(dir)) {
      Warning("InodeOpLookup: invalid inode provided\n");
      return ERR_PTR(-EINVAL);
   }

   /* Get a slab from the kernel's names_cache of PATH_MAX-sized buffers. */
   filename = __getname();
   if (!filename) {
      Warning("InodeOpLookup: unable to obtain memory for filename.\n");
      return ERR_PTR(-ENOMEM);
   }

   ret = MakeFullName(dir, dentry, filename, PATH_MAX);
   if (ret < 0) {
      Warning("InodeOpLookup: could not construct full name\n");
      __putname(filename);
      return ERR_PTR(ret);
   }

   /* Block if there is a pending block on this file */
   BlockWaitOnFile(filename, NULL);
   __putname(filename);

   inode = Iget(dir->i_sb, dir, dentry, GetNextIno());
   if (!inode) {
      Warning("InodeOpLookup: failed to get inode\n");
      return ERR_PTR(-ENOMEM);
   }

   dentry->d_op = &LinkDentryOps;
   dentry->d_time = jiffies;

   /*
    * If the actual file's dentry doesn't have an inode, it means the file we
    * are redirecting to doesn't exist.  Give back the inode that was created
    * for this and add a NULL dentry->inode entry in the dcache.  (The NULL
    * entry is added so ops to create files/directories are invoked by VFS.)
    */
   if (!INODE_TO_ACTUALDENTRY(inode) || !INODE_TO_ACTUALINODE(inode)) {
      iput(inode);
      d_add(dentry, NULL);
      return NULL;
   }

   inode->i_mode = S_IFLNK | S_IRWXUGO;
   inode->i_size = INODE_TO_IINFO(inode)->nameLen;
   inode->i_version = 1;
   inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
   inode->i_uid = inode->i_gid = 0;
   inode->i_op = &LinkInodeOps;

   d_add(dentry, inode);
   return NULL;
}
Exemple #19
0
static int process_measurement(struct file *file, int mask, int function,
			       int opened)
{
	struct inode *inode = file_inode(file);
	struct integrity_iint_cache *iint = NULL;
	struct ima_template_desc *template_desc;
	char *pathbuf = NULL;
	const char *pathname = NULL;
	int rc = -ENOMEM, action, must_appraise;
	struct evm_ima_xattr_data *xattr_value = NULL, **xattr_ptr = NULL;
	int xattr_len = 0;
	bool violation_check;

	if (!ima_policy_flag || !S_ISREG(inode->i_mode))
		return 0;

	/* Return an IMA_MEASURE, IMA_APPRAISE, IMA_AUDIT action
	 * bitmask based on the appraise/audit/measurement policy.
	 * Included is the appraise submask.
	 */
	action = ima_get_action(inode, mask, function);
	violation_check = ((function == FILE_CHECK || function == MMAP_CHECK) &&
			   (ima_policy_flag & IMA_MEASURE));
	if (!action && !violation_check)
		return 0;

	must_appraise = action & IMA_APPRAISE;

	/*  Is the appraise rule hook specific?  */
	if (action & IMA_FILE_APPRAISE)
		function = FILE_CHECK;

	mutex_lock(&inode->i_mutex);

	if (action) {
		iint = integrity_inode_get(inode);
		if (!iint)
			goto out;
	}

	if (violation_check) {
		ima_rdwr_violation_check(file, iint, action & IMA_MEASURE,
					 &pathbuf, &pathname);
		if (!action) {
			rc = 0;
			goto out_free;
		}
	}

	/* Determine if already appraised/measured based on bitmask
	 * (IMA_MEASURE, IMA_MEASURED, IMA_XXXX_APPRAISE, IMA_XXXX_APPRAISED,
	 *  IMA_AUDIT, IMA_AUDITED)
	 */
	iint->flags |= action;
	action &= IMA_DO_MASK;
	action &= ~((iint->flags & IMA_DONE_MASK) >> 1);

	/* Nothing to do, just return existing appraised status */
	if (!action) {
		if (must_appraise)
			rc = ima_get_cache_status(iint, function);
		goto out_digsig;
	}

	template_desc = ima_template_desc_current();
	if ((action & IMA_APPRAISE_SUBMASK) ||
		    strcmp(template_desc->name, IMA_TEMPLATE_IMA_NAME) != 0)
		xattr_ptr = &xattr_value;

	rc = ima_collect_measurement(iint, file, xattr_ptr, &xattr_len);
	if (rc != 0) {
		if (file->f_flags & O_DIRECT)
			rc = (iint->flags & IMA_PERMIT_DIRECTIO) ? 0 : -EACCES;
		goto out_digsig;
	}

	if (!pathname)	/* ima_rdwr_violation possibly pre-fetched */
		pathname = ima_d_path(&file->f_path, &pathbuf);

	if (action & IMA_MEASURE)
		ima_store_measurement(iint, file, pathname,
				      xattr_value, xattr_len);
	if (action & IMA_APPRAISE_SUBMASK)
		rc = ima_appraise_measurement(function, iint, file, pathname,
					      xattr_value, xattr_len, opened);
	if (action & IMA_AUDIT)
		ima_audit_measurement(iint, pathname);

out_digsig:
	if ((mask & MAY_WRITE) && (iint->flags & IMA_DIGSIG))
		rc = -EACCES;
	kfree(xattr_value);
out_free:
	if (pathbuf)
		__putname(pathbuf);
out:
	mutex_unlock(&inode->i_mutex);
	if ((rc && must_appraise) && (ima_appraise & IMA_APPRAISE_ENFORCE))
		return -EACCES;
	return 0;
}
Exemple #20
0
static int process_measurement(struct file *file, const struct cred *cred,
			       u32 secid, char *buf, loff_t size, int mask,
			       enum ima_hooks func, int opened)
{
	struct inode *inode = file_inode(file);
	struct integrity_iint_cache *iint = NULL;
	struct ima_template_desc *template_desc;
	char *pathbuf = NULL;
	char filename[NAME_MAX];
	const char *pathname = NULL;
	int rc = 0, action, must_appraise = 0;
	int pcr = CONFIG_IMA_MEASURE_PCR_IDX;
	struct evm_ima_xattr_data *xattr_value = NULL;
	int xattr_len = 0;
	bool violation_check;
	enum hash_algo hash_algo;

	if (!ima_policy_flag || !S_ISREG(inode->i_mode))
		return 0;

	/* Return an IMA_MEASURE, IMA_APPRAISE, IMA_AUDIT action
	 * bitmask based on the appraise/audit/measurement policy.
	 * Included is the appraise submask.
	 */
	action = ima_get_action(inode, cred, secid, mask, func, &pcr);
	violation_check = ((func == FILE_CHECK || func == MMAP_CHECK) &&
			   (ima_policy_flag & IMA_MEASURE));
	if (!action && !violation_check)
		return 0;

	must_appraise = action & IMA_APPRAISE;

	/*  Is the appraise rule hook specific?  */
	if (action & IMA_FILE_APPRAISE)
		func = FILE_CHECK;

	inode_lock(inode);

	if (action) {
		iint = integrity_inode_get(inode);
		if (!iint)
			rc = -ENOMEM;
	}

	if (!rc && violation_check)
		ima_rdwr_violation_check(file, iint, action & IMA_MEASURE,
					 &pathbuf, &pathname, filename);

	inode_unlock(inode);

	if (rc)
		goto out;
	if (!action)
		goto out;

	mutex_lock(&iint->mutex);

	if (test_and_clear_bit(IMA_CHANGE_ATTR, &iint->atomic_flags))
		/* reset appraisal flags if ima_inode_post_setattr was called */
		iint->flags &= ~(IMA_APPRAISE | IMA_APPRAISED |
				 IMA_APPRAISE_SUBMASK | IMA_APPRAISED_SUBMASK |
				 IMA_ACTION_FLAGS);

	/*
	 * Re-evaulate the file if either the xattr has changed or the
	 * kernel has no way of detecting file change on the filesystem.
	 * (Limited to privileged mounted filesystems.)
	 */
	if (test_and_clear_bit(IMA_CHANGE_XATTR, &iint->atomic_flags) ||
	    ((inode->i_sb->s_iflags & SB_I_IMA_UNVERIFIABLE_SIGNATURE) &&
	     !(inode->i_sb->s_iflags & SB_I_UNTRUSTED_MOUNTER) &&
	     !(action & IMA_FAIL_UNVERIFIABLE_SIGS))) {
		iint->flags &= ~IMA_DONE_MASK;
		iint->measured_pcrs = 0;
	}

	/* Determine if already appraised/measured based on bitmask
	 * (IMA_MEASURE, IMA_MEASURED, IMA_XXXX_APPRAISE, IMA_XXXX_APPRAISED,
	 *  IMA_AUDIT, IMA_AUDITED)
	 */
	iint->flags |= action;
	action &= IMA_DO_MASK;
	action &= ~((iint->flags & (IMA_DONE_MASK ^ IMA_MEASURED)) >> 1);

	/* If target pcr is already measured, unset IMA_MEASURE action */
	if ((action & IMA_MEASURE) && (iint->measured_pcrs & (0x1 << pcr)))
		action ^= IMA_MEASURE;

	/* HASH sets the digital signature and update flags, nothing else */
	if ((action & IMA_HASH) &&
	    !(test_bit(IMA_DIGSIG, &iint->atomic_flags))) {
		xattr_len = ima_read_xattr(file_dentry(file), &xattr_value);
		if ((xattr_value && xattr_len > 2) &&
		    (xattr_value->type == EVM_IMA_XATTR_DIGSIG))
			set_bit(IMA_DIGSIG, &iint->atomic_flags);
		iint->flags |= IMA_HASHED;
		action ^= IMA_HASH;
		set_bit(IMA_UPDATE_XATTR, &iint->atomic_flags);
	}

	/* Nothing to do, just return existing appraised status */
	if (!action) {
		if (must_appraise)
			rc = ima_get_cache_status(iint, func);
		goto out_locked;
	}

	template_desc = ima_template_desc_current();
	if ((action & IMA_APPRAISE_SUBMASK) ||
		    strcmp(template_desc->name, IMA_TEMPLATE_IMA_NAME) != 0)
		/* read 'security.ima' */
		xattr_len = ima_read_xattr(file_dentry(file), &xattr_value);

	hash_algo = ima_get_hash_algo(xattr_value, xattr_len);

	rc = ima_collect_measurement(iint, file, buf, size, hash_algo);
	if (rc != 0 && rc != -EBADF && rc != -EINVAL)
		goto out_locked;

	if (!pathbuf)	/* ima_rdwr_violation possibly pre-fetched */
		pathname = ima_d_path(&file->f_path, &pathbuf, filename);

	if (action & IMA_MEASURE)
		ima_store_measurement(iint, file, pathname,
				      xattr_value, xattr_len, pcr);
	if (rc == 0 && (action & IMA_APPRAISE_SUBMASK)) {
		inode_lock(inode);
		rc = ima_appraise_measurement(func, iint, file, pathname,
					      xattr_value, xattr_len, opened);
		inode_unlock(inode);
	}
	if (action & IMA_AUDIT)
		ima_audit_measurement(iint, pathname);

	if ((file->f_flags & O_DIRECT) && (iint->flags & IMA_PERMIT_DIRECTIO))
		rc = 0;
out_locked:
	if ((mask & MAY_WRITE) && test_bit(IMA_DIGSIG, &iint->atomic_flags) &&
	     !(iint->flags & IMA_NEW_FILE))
		rc = -EACCES;
	mutex_unlock(&iint->mutex);
	kfree(xattr_value);
out:
	if (pathbuf)
		__putname(pathbuf);
	if (must_appraise) {
		if (rc && (ima_appraise & IMA_APPRAISE_ENFORCE))
			return -EACCES;
		if (file->f_mode & FMODE_WRITE)
			set_bit(IMA_UPDATE_XATTR, &iint->atomic_flags);
	}
	return 0;
}
Exemple #21
0
/* 
 * @inode:  svfs inode
 */
int llfs_lookup(struct inode *inode)
{
    struct svfs_datastore *sd;
    struct dentry *llfs_dentry;
    const struct cred *cred = current_cred();
    struct nameidata llfs_nd;
    char *ref_path;
    int err = 0;
    
    if (S_ISDIR(inode->i_mode))
        goto out;
    if (SVFS_I(inode)->state & SVFS_STATE_DA)
        goto out;
    if (SVFS_I(inode)->state & SVFS_STATE_CONN)
        goto out;

    err = -ENOMEM;
    ref_path = __getname();
    if (!ref_path)
        goto out;

    err = -EINVAL;
    sd = svfs_datastore_get(SVFS_I(inode)->llfs_md.llfs_type,
                            SVFS_I(inode)->llfs_md.llfs_fsid);
    if (!sd)
        goto out_release_name;
    sprintf(ref_path, "%s%s", sd->pathname,
            SVFS_I(inode)->llfs_md.llfs_pathname);
    svfs_debug(mdc, "fully ref_path %s\n", ref_path);

    err = path_lookup(ref_path, LOOKUP_FOLLOW, &llfs_nd);
    if (err)
        goto fail_lookup;
    SVFS_I(inode)->llfs_md.llfs_filp = dentry_open(llfs_nd.path.dentry,
                                                   llfs_nd.path.mnt,
                                                   O_RDWR,
                                                   cred);
    if (IS_ERR(SVFS_I(inode)->llfs_md.llfs_filp))
        goto out_put_path;

    llfs_dentry = svfs_relay(lookup,
                             SVFS_I(inode)->llfs_md.llfs_type, inode);
    if (IS_ERR(llfs_dentry)) {
        SVFS_I(inode)->state |= SVFS_STATE_DISC;
        svfs_err(mdc, "svfs_relay 'lookup' failed %ld\n",
                 PTR_ERR(llfs_dentry));
        goto out_put_filp;
    }
    SVFS_I(inode)->state |= SVFS_STATE_CONN;
    err = 0;
out:
    return err;

out_put_filp:
    fput(SVFS_I(inode)->llfs_md.llfs_filp);
    goto out;
out_put_path:
    /* path_put(&llfs_nd.path) */
    {
        svfs_debug(mdc, "llfs_nd.path->dentry %d, vfsmount %d\n",
                   atomic_read(&llfs_nd.path.dentry->d_count),
                   atomic_read(&llfs_nd.path.mnt->mnt_count));
    }
    goto out;
fail_lookup:
out_release_name:
    __putname(ref_path);
    goto out;
}
Exemple #22
0
/* cr_mknod - based on linux/fs/namei.c:sys_mknod
 *
 * Creates regular files or fifos (no devices) making them anonymous (unlinked)
 * if desired.
 * Returns a dentry for the resulting filesystem objects, and the corresponding
 * vfsmnt can be obtained in nd->mnt.  Together these two can be passed
 * to dentry_open() or cr_dentry_open(), even for an unlinked inode.
 * In the event of an error, no dput() or cr_path_release() is required,
 * otherwise they are.
 *
 * In the event that an object exists with the given name, it will be
 * check for the proper mode prior to return, yielding -EEXIST on conflict.
 */
struct dentry *
cr_mknod(cr_errbuf_t *eb, struct nameidata *nd, const char *name, int mode, unsigned long unlinked_id)
{
    struct dentry * dentry;
    int err;

    if (unlinked_id) {
	/* Generate a replacement name which we will use instead of the original one. */
	name = cr_anonymous_rename(eb, name, unlinked_id);
	if (!name) {
	    CR_ERR_EB(eb, "cr_mknod - failed to rename unlinked object");
	    err = -ENOMEM;
	    goto out;
	}
    }

    /* Prior to 2.6.26, lookup_create() would return an exisiting dentry.
     * Since 2.6.26, it returns -EEXIST if the dentry exists.  So, we first
     * check for an existing dentry.  For older kernels this is not required,
     * but is still correct.
     */
    err = path_lookup(name, LOOKUP_FOLLOW, nd);
    if (!err) {
	dentry = dget(nd->nd_dentry);
	err = -EEXIST; /* Forces mode validation below */
	goto have_it;
    }

    err = path_lookup(name, LOOKUP_PARENT, nd);
    if (err) {
	CR_KTRACE_UNEXPECTED("Couldn't path_lookup for mknod %s.  err=%d.", name, err);
	goto out_free;
    }

    dentry = cr_lookup_create(nd, 0);
    if (IS_ERR(dentry)) {
	err = PTR_ERR(dentry);
	CR_KTRACE_UNEXPECTED("Couldn't lookup_create for mknod %s.  err=%d.", name, err);
	goto out_release;
    }

    switch (mode & S_IFMT) {
    case S_IFREG:
	err = vfs_create(nd->nd_dentry->d_inode, dentry, mode, nd);
	break;
    case S_IFIFO:
	err = cr_vfs_mknod(nd->nd_dentry->d_inode, dentry, nd->nd_mnt, mode, 0 /* ignored */);
	break;
    default:
	CR_ERR_EB(eb, "Unknown/invalid type %d passed to cr_mknod %s.", (mode&S_IFMT), name);
	err = -EINVAL;
    }
    if (unlinked_id && !err) { /* Note that we don't unlink if we failed to create */
	dget(dentry);	/* ensure unlink doesn't destroy the dentry */
	/* Note possibility of silent failure here: */
	(void)cr_vfs_unlink(nd->nd_dentry->d_inode, dentry, nd->nd_mnt);
	dput(dentry);
    }
    cr_inode_unlock(nd->nd_dentry->d_inode);

have_it:
    if ((err == -EEXIST) && !((dentry->d_inode->i_mode ^ mode) & S_IFMT)) {
	/* We fall through and return the dentry */
    } else if (err) {
	CR_KTRACE_UNEXPECTED("Couldn't cr_mknod %s.  err=%d.", name, err);
	goto out_put;
    }

    if (unlinked_id) {
	__putname(name);
    }
    return dentry;

out_put:
    dput(dentry);
out_release:
    cr_path_release(nd);
out_free:
    if (unlinked_id) {
	__putname(name);
    }
out:
    return (struct dentry *)ERR_PTR(err);
}
Exemple #23
0
static struct dentry *au_lkup_by_ino(struct path *path, ino_t ino,
				     struct au_nfsd_si_lock *nsi_lock)
{
	struct dentry *dentry, *parent;
	struct file *file;
	struct inode *dir;
	struct find_name_by_ino arg;
	int err;

	parent = path->dentry;
	if (nsi_lock)
		si_read_unlock(parent->d_sb);
	file = vfsub_dentry_open(path, au_dir_roflags);
	dentry = (void *)file;
	if (IS_ERR(file))
		goto out;

	dentry = ERR_PTR(-ENOMEM);
	arg.name = __getname_gfp(GFP_NOFS);
	if (unlikely(!arg.name))
		goto out_file;
	arg.ino = ino;
	arg.found = 0;
	do {
		arg.called = 0;
		/* smp_mb(); */
		err = vfsub_readdir(file, find_name_by_ino, &arg);
	} while (!err && !arg.found && arg.called);
	dentry = ERR_PTR(err);
	if (unlikely(err))
		goto out_name;
	dentry = ERR_PTR(-ENOENT);
	if (!arg.found)
		goto out_name;

	/* do not call au_lkup_one() */
	dir = parent->d_inode;
	mutex_lock(&dir->i_mutex);
	dentry = vfsub_lookup_one_len(arg.name, parent, arg.namelen);
	mutex_unlock(&dir->i_mutex);
	AuTraceErrPtr(dentry);
	if (IS_ERR(dentry))
		goto out_name;
	AuDebugOn(au_test_anon(dentry));
	if (unlikely(!dentry->d_inode)) {
		dput(dentry);
		dentry = ERR_PTR(-ENOENT);
	}

 out_name:
	__putname(arg.name);
 out_file:
	fput(file);
 out:
	if (unlikely(nsi_lock
		     && si_nfsd_read_lock(parent->d_sb, nsi_lock) < 0))
		if (!IS_ERR(dentry)) {
			dput(dentry);
			dentry = ERR_PTR(-ESTALE);
		}
	AuTraceErrPtr(dentry);
	return dentry;
}
Exemple #24
0
struct p9_fid *v9fs_session_init(struct v9fs_session_info *v9ses,
          const char *dev_name, char *data)
{
    int retval = -EINVAL;
    struct p9_fid *fid;
    int rc;

    v9ses->uname = __getname();
    if (!v9ses->uname)
        return ERR_PTR(-ENOMEM);

    v9ses->aname = __getname();
    if (!v9ses->aname) {
        __putname(v9ses->uname);
        return ERR_PTR(-ENOMEM);
    }

    v9ses->flags = V9FS_EXTENDED | V9FS_ACCESS_USER;
    strcpy(v9ses->uname, V9FS_DEFUSER);
    strcpy(v9ses->aname, V9FS_DEFANAME);
    v9ses->uid = ~0;
    v9ses->dfltuid = V9FS_DEFUID;
    v9ses->dfltgid = V9FS_DEFGID;
    if (data) {
        v9ses->options = kstrdup(data, GFP_KERNEL);
        if (!v9ses->options) {
            P9_DPRINTK(P9_DEBUG_ERROR,
               "failed to allocate copy of option string\n");
            retval = -ENOMEM;
            goto error;
        }
    }

    rc = v9fs_parse_options(v9ses);
    if (rc < 0) {
        retval = rc;
        goto error;
    }

    v9ses->clnt = p9_client_create(dev_name, v9ses->options);

    if (IS_ERR(v9ses->clnt)) {
        retval = PTR_ERR(v9ses->clnt);
        v9ses->clnt = NULL;
        P9_DPRINTK(P9_DEBUG_ERROR, "problem initializing 9p client\n");
        goto error;
    }

    if (!v9ses->clnt->dotu)
        v9ses->flags &= ~V9FS_EXTENDED;

    v9ses->maxdata = v9ses->clnt->msize;

    /* for legacy mode, fall back to V9FS_ACCESS_ANY */
    if (!v9fs_extended(v9ses) &&
        ((v9ses->flags&V9FS_ACCESS_MASK) == V9FS_ACCESS_USER)) {

        v9ses->flags &= ~V9FS_ACCESS_MASK;
        v9ses->flags |= V9FS_ACCESS_ANY;
        v9ses->uid = ~0;
    }

    fid = p9_client_attach(v9ses->clnt, NULL, v9ses->uname, ~0,
                            v9ses->aname);
    if (IS_ERR(fid)) {
        retval = PTR_ERR(fid);
        fid = NULL;
        P9_DPRINTK(P9_DEBUG_ERROR, "cannot attach\n");
        goto error;
    }

    if ((v9ses->flags & V9FS_ACCESS_MASK) == V9FS_ACCESS_SINGLE)
        fid->uid = v9ses->uid;
    else
        fid->uid = ~0;

    return fid;

error:
    return ERR_PTR(retval);
}
Exemple #25
0
int
v9fs_session_init(struct v9fs_session_info *v9ses,
		  const char *dev_name, char *data)
{
	struct v9fs_fcall *fcall = NULL;
	struct v9fs_transport *trans_proto;
	int n = 0;
	int newfid = -1;
	int retval = -EINVAL;
	struct v9fs_str *version;

	v9ses->name = __getname();
	if (!v9ses->name)
		return -ENOMEM;

	v9ses->remotename = __getname();
	if (!v9ses->remotename) {
		__putname(v9ses->name);
		return -ENOMEM;
	}

	strcpy(v9ses->name, V9FS_DEFUSER);
	strcpy(v9ses->remotename, V9FS_DEFANAME);

	v9fs_parse_options(data, v9ses);

	/* set global debug level */
	v9fs_debug_level = v9ses->debug;

	/* id pools that are session-dependent: fids and tags */
	idr_init(&v9ses->fidpool.pool);
	init_MUTEX(&v9ses->fidpool.lock);

	switch (v9ses->proto) {
	case PROTO_TCP:
		trans_proto = &v9fs_trans_tcp;
		break;
	case PROTO_UNIX:
		trans_proto = &v9fs_trans_unix;
		*v9ses->remotename = 0;
		break;
	case PROTO_FD:
		trans_proto = &v9fs_trans_fd;
		*v9ses->remotename = 0;
		break;
	default:
		printk(KERN_ERR "v9fs: Bad mount protocol %d\n", v9ses->proto);
		retval = -ENOPROTOOPT;
		goto SessCleanUp;
	};

	v9ses->transport = kmalloc(sizeof(*v9ses->transport), GFP_KERNEL);
	if (!v9ses->transport) {
		retval = -ENOMEM;
		goto SessCleanUp;
	}

	memmove(v9ses->transport, trans_proto, sizeof(*v9ses->transport));

	if ((retval = v9ses->transport->init(v9ses, dev_name, data)) < 0) {
		eprintk(KERN_ERR, "problem initializing transport\n");
		goto SessCleanUp;
	}

	v9ses->inprogress = 0;
	v9ses->shutdown = 0;
	v9ses->session_hung = 0;

	v9ses->mux = v9fs_mux_init(v9ses->transport, v9ses->maxdata + V9FS_IOHDRSZ,
		&v9ses->extended);

	if (IS_ERR(v9ses->mux)) {
		retval = PTR_ERR(v9ses->mux);
		v9ses->mux = NULL;
		dprintk(DEBUG_ERROR, "problem initializing mux\n");
		goto SessCleanUp;
	}

	if (v9ses->afid == ~0) {
		if (v9ses->extended)
			retval =
			    v9fs_t_version(v9ses, v9ses->maxdata, "9P2000.u",
					   &fcall);
		else
			retval = v9fs_t_version(v9ses, v9ses->maxdata, "9P2000",
						&fcall);

		if (retval < 0) {
			dprintk(DEBUG_ERROR, "v9fs_t_version failed\n");
			goto FreeFcall;
		}

		version = &fcall->params.rversion.version;
		if (version->len==8 && !memcmp(version->str, "9P2000.u", 8)) {
			dprintk(DEBUG_9P, "9P2000 UNIX extensions enabled\n");
			v9ses->extended = 1;
		} else if (version->len==6 && !memcmp(version->str, "9P2000", 6)) {
			dprintk(DEBUG_9P, "9P2000 legacy mode enabled\n");
			v9ses->extended = 0;
		} else {
			retval = -EREMOTEIO;
			goto FreeFcall;
		}

		n = fcall->params.rversion.msize;
		kfree(fcall);

		if (n < v9ses->maxdata)
			v9ses->maxdata = n;
	}

	newfid = v9fs_get_idpool(&v9ses->fidpool);
	if (newfid < 0) {
		eprintk(KERN_WARNING, "couldn't allocate FID\n");
		retval = -ENOMEM;
		goto SessCleanUp;
	}
	/* it is a little bit ugly, but we have to prevent newfid */
	/* being the same as afid, so if it is, get a new fid     */
	if (v9ses->afid != ~0 && newfid == v9ses->afid) {
		newfid = v9fs_get_idpool(&v9ses->fidpool);
		if (newfid < 0) {
			eprintk(KERN_WARNING, "couldn't allocate FID\n");
			retval = -ENOMEM;
			goto SessCleanUp;
		}
	}

	if ((retval =
	     v9fs_t_attach(v9ses, v9ses->name, v9ses->remotename, newfid,
			   v9ses->afid, NULL))
	    < 0) {
		dprintk(DEBUG_ERROR, "cannot attach\n");
		goto SessCleanUp;
	}

	if (v9ses->afid != ~0) {
		dprintk(DEBUG_ERROR, "afid not equal to ~0\n");
		if (v9fs_t_clunk(v9ses, v9ses->afid))
			dprintk(DEBUG_ERROR, "clunk failed\n");
	}

	return newfid;

      FreeFcall:
	kfree(fcall);

      SessCleanUp:
	v9fs_session_close(v9ses);
	return retval;
}
Exemple #26
0
static struct dentry *au_lkup_by_ino(struct path *path, ino_t ino,
				     struct au_nfsd_si_lock *nsi_lock)
{
	struct dentry *dentry, *parent;
	struct file *file;
	struct inode *dir;
	struct find_name_by_ino arg;
	int err;

	parent = path->dentry;
	LKTRTrace("%.*s, i%lu\n", AuDLNPair(parent), (unsigned long)ino);

	if (nsi_lock)
		si_read_unlock(parent->d_sb);
	path_get(path);
	file = dentry_open(parent, path->mnt, au_dir_roflags);
	dentry = (void *)file;
	if (IS_ERR(file))
		goto out;

	dentry = ERR_PTR(-ENOMEM);
	arg.name = __getname();
	if (unlikely(!arg.name))
		goto out_file;
	arg.ino = ino;
	arg.found = 0;
	do {
		arg.called = 0;
		/* smp_mb(); */
		err = vfsub_readdir(file, find_name_by_ino, &arg, /*dlgt*/0);
	} while (!err && !arg.found && arg.called);
	dentry = ERR_PTR(err);
	if (unlikely(err))
		goto out_name;
	dentry = ERR_PTR(-ENOENT);
	if (!arg.found)
		goto out_name;

	/* do not call au_lkup_one(), nor dlgt */
	dir = parent->d_inode;
	vfsub_i_lock(dir);
	dentry = vfsub_lookup_one_len(arg.name, parent, arg.namelen);
	vfsub_i_unlock(dir);
	AuTraceErrPtr(dentry);
	if (IS_ERR(dentry))
		goto out_name;
	AuDebugOn(au_test_anon(dentry));
	if (unlikely(!dentry->d_inode)) {
		dput(dentry);
		dentry = ERR_PTR(-ENOENT);
	}

 out_name:
	__putname(arg.name);
 out_file:
	fput(file);
 out:
	if (unlikely(nsi_lock
		     && si_nfsd_read_lock(parent->d_sb, nsi_lock) < 0))
		if (!IS_ERR(dentry)) {
			dput(dentry);
			dentry = ERR_PTR(-ESTALE);
		}
	AuTraceErrPtr(dentry);
	return dentry;
}
Exemple #27
0
struct p9_fid *v9fs_session_init(struct v9fs_session_info *v9ses,
		  const char *dev_name, char *data)
{
	int retval = -EINVAL;
	struct p9_transport *trans;
	struct p9_fid *fid;

	v9ses->name = __getname();
	if (!v9ses->name)
		return ERR_PTR(-ENOMEM);

	v9ses->remotename = __getname();
	if (!v9ses->remotename) {
		__putname(v9ses->name);
		return ERR_PTR(-ENOMEM);
	}

	strcpy(v9ses->name, V9FS_DEFUSER);
	strcpy(v9ses->remotename, V9FS_DEFANAME);

	v9fs_parse_options(data, v9ses);

	switch (v9ses->proto) {
	case PROTO_TCP:
		trans = p9_trans_create_tcp(dev_name, v9ses->port);
		break;
	case PROTO_UNIX:
		trans = p9_trans_create_unix(dev_name);
		*v9ses->remotename = 0;
		break;
	case PROTO_FD:
		trans = p9_trans_create_fd(v9ses->rfdno, v9ses->wfdno);
		*v9ses->remotename = 0;
		break;
#ifdef CONFIG_PCI_9P
	case PROTO_PCI:
		trans = p9pci_trans_create();
		*v9ses->remotename = 0;
		break;
#endif
	default:
		printk(KERN_ERR "v9fs: Bad mount protocol %d\n", v9ses->proto);
		retval = -ENOPROTOOPT;
		goto error;
	};

	if (IS_ERR(trans)) {
		retval = PTR_ERR(trans);
		trans = NULL;
		goto error;
	}

	v9ses->clnt = p9_client_create(trans, v9ses->maxdata + P9_IOHDRSZ,
		v9ses->extended);

	if (IS_ERR(v9ses->clnt)) {
		retval = PTR_ERR(v9ses->clnt);
		v9ses->clnt = NULL;
		P9_DPRINTK(P9_DEBUG_ERROR, "problem initializing 9p client\n");
		goto error;
	}

	fid = p9_client_attach(v9ses->clnt, NULL, v9ses->name,
							v9ses->remotename);
	if (IS_ERR(fid)) {
		retval = PTR_ERR(fid);
		fid = NULL;
		P9_DPRINTK(P9_DEBUG_ERROR, "cannot attach\n");
		goto error;
	}

	return fid;

error:
	v9fs_session_close(v9ses);
	return ERR_PTR(retval);
}
Exemple #28
0
static void smb_put_link(struct dentry *dentry, struct nameidata *nd)
{
	char *s = nd_get_link(nd);
	if (!IS_ERR(s))
		__putname(s);
}
Exemple #29
0
/* cr_mknod
 *
 * Creates regular files or fifos (no devices) making them anonymous (unlinked)
 * if desired, populating the struct path appropriatly.
 * In the event of an error, no dput() or path_put() is required,
 * otherwise they are.
 *
 * In the event that an object exists with the given name, it will be
 * check for the proper mode prior to return, yielding -EEXIST on conflict.
 */
int
cr_mknod(cr_errbuf_t *eb, struct path *path, const char *name, int mode, unsigned long unlinked_id)
{
    mm_segment_t oldfs;
    int err;

#if CRI_DEBUG
    /* first validate mode */
    switch (mode & S_IFMT) {
    case S_IFREG:
    case S_IFIFO:
	break;
    default:
	CR_ERR_EB(eb, "Unknown/invalid type %d passed to cr_mknod %s.", (mode&S_IFMT), name);
	err = -EINVAL;
	goto out;
    }
#endif

    if (unlinked_id) {
	/* Generate a replacement name which we will use instead of the original one. */
	name = cr_anonymous_rename(eb, name, unlinked_id);
	if (!name) {
	    CR_ERR_EB(eb, "cr_mknod - failed to rename unlinked object");
	    err = -ENOMEM;
	    goto out;
	}
    }

    /* sys_mknod() */
    oldfs = get_fs();
    set_fs(KERNEL_DS);
    err = sys_mknod(name, mode, 0);
    set_fs(oldfs);
    if (err == -EEXIST) {
	/* Keep going, it may be the one we want */
    } else if (err < 0) {
	goto out_free;
    }

    /* Now get the (struct path) for the newly-created object.
     * YES, there is a potential race, but we check below that we have the right object.
     */
    err = cr_kern_path(name, LOOKUP_FOLLOW, path);
    if (err < 0) {
	CR_ERR_EB(eb, "cr_mknod: cr_kern_path(%s) returned %d after sys_mknod()", name, err);
	goto out_free;
    }

    /* Check that we have the desired object type.
     * Needed for sys_mknod() == -EEXIST and for the mknod-to-lookup race.
     */
    if ((path->dentry->d_inode->i_mode ^ mode) & S_IFMT) {
	CR_ERR_EB(eb, "cr_mknod: cr_kern_path(%s) found conflicting object", name);
	err = -EEXIST;
	path_put(path);
	goto out_free;
    }

    /* unlink if required */
    if (unlinked_id) {
	/* Note possibility of silent failure here: */
	oldfs = get_fs();
	set_fs(KERNEL_DS);
	(void) sys_unlink(name);
	set_fs(oldfs);
    }

out_free:
    if (unlinked_id) {
	__putname(name);
    }
out:
    return err;
}