static int bpf_obj_do_pin(const struct filename *pathname, void *raw, enum bpf_type type) { struct dentry *dentry; struct inode *dir; struct path path; umode_t mode; dev_t devt; int ret; dentry = kern_path_create(AT_FDCWD, pathname->name, &path, 0); if (IS_ERR(dentry)) return PTR_ERR(dentry); mode = S_IFREG | ((S_IRUSR | S_IWUSR) & ~current_umask()); devt = MKDEV(UNNAMED_MAJOR, type); ret = security_path_mknod(&path, dentry, mode, devt); if (ret) goto out; dir = d_inode(path.dentry); if (dir->i_op != &bpf_dir_iops) { ret = -EPERM; goto out; } dentry->d_fsdata = raw; ret = vfs_mknod(dir, dentry, mode, devt); dentry->d_fsdata = NULL; out: done_path_create(&path, dentry); return ret; }
int vfsub_mknod(struct inode *dir, struct path *path, int mode, dev_t dev) { int err; struct dentry *d; IMustLock(dir); d = path->dentry; path->dentry = d->d_parent; err = security_path_mknod(path, d, mode, new_encode_dev(dev)); path->dentry = d; if (unlikely(err)) goto out; err = vfs_mknod(dir, path->dentry, mode, dev); if (!err) { struct path tmp = *path; int did; vfsub_update_h_iattr(&tmp, &did); if (did) { tmp.dentry = path->dentry->d_parent; vfsub_update_h_iattr(&tmp, /*did*/NULL); } /*ignore*/ } out: return err; }
int vfsub_create(struct inode *dir, struct path *path, int mode, bool want_excl) { int err; struct dentry *d; IMustLock(dir); d = path->dentry; path->dentry = d->d_parent; err = security_path_mknod(path, d, mode, 0); path->dentry = d; if (unlikely(err)) goto out; lockdep_off(); err = vfs_create(dir, path->dentry, mode, want_excl); lockdep_on(); if (!err) { struct path tmp = *path; int did; vfsub_update_h_iattr(&tmp, &did); if (did) { tmp.dentry = path->dentry->d_parent; vfsub_update_h_iattr(&tmp, /*did*/NULL); } /*ignore*/ } out: return err; }
int vfsub_create(struct inode *dir, struct path *path, int mode) { int err; struct dentry *d; IMustLock(dir); d = path->dentry; path->dentry = d->d_parent; err = security_path_mknod(path, d, mode, 0); path->dentry = d; if (unlikely(err)) goto out; if (au_test_fs_null_nd(dir->i_sb)) err = vfs_create(dir, path->dentry, mode, NULL); else { struct nameidata h_nd; memset(&h_nd, 0, sizeof(h_nd)); h_nd.flags = LOOKUP_CREATE; h_nd.intent.open.flags = O_CREAT | vfsub_fmode_to_uint(FMODE_READ); h_nd.intent.open.create_mode = mode; h_nd.path.dentry = path->dentry->d_parent; h_nd.path.mnt = path->mnt; path_get(&h_nd.path); err = vfs_create(dir, path->dentry, mode, &h_nd); path_put(&h_nd.path); } if (!err) { struct path tmp = *path; int did; vfsub_update_h_iattr(&tmp, &did); if (did) { tmp.dentry = path->dentry->d_parent; vfsub_update_h_iattr(&tmp, /*did*/NULL); } /*ignore*/ } out: return err; }
//==================================================================== // Create a node for this device under the given path using the given // device number. Returns 0 on success and non-zero on failure. static int create_fs_node(const char *dev_path, dev_t undelete_minor_devnode) { struct dentry *dentry; struct path path; int lookup_flags = 0; umode_t mode = S_IRUGO | S_IFCHR; int err; dentry = kern_path_create(AT_FDCWD, dev_path, &path, lookup_flags); if (IS_ERR(dentry)) { return PTR_ERR(dentry); } err = security_path_mknod(&path, dentry, mode, undelete_minor_devnode); if (!err) { err = vfs_mknod(path.dentry->d_inode, dentry, mode, undelete_minor_devnode); } done_path_create(&path, dentry); return err; }