/** * ubi_open_volume_path - open UBI volume by its character device node path. * @pathname: volume character device node path * @mode: open mode * * This function is similar to 'ubi_open_volume()', but opens a volume the path * to its character device node. */ struct ubi_volume_desc *ubi_open_volume_path(const char *pathname, int mode) { int error, ubi_num, vol_id, mod; struct inode *inode; struct path path; dbg_gen("open volume %s, mode %d", pathname, mode); if (!pathname || !*pathname) return ERR_PTR(-EINVAL); error = kern_path(pathname, LOOKUP_FOLLOW, &path); if (error) return ERR_PTR(error); inode = path.dentry->d_inode; mod = inode->i_mode; ubi_num = ubi_major2num(imajor(inode)); vol_id = iminor(inode) - 1; path_put(&path); if (!S_ISCHR(mod)) return ERR_PTR(-EINVAL); if (vol_id >= 0 && ubi_num >= 0) return ubi_open_volume(ubi_num, vol_id, mode); return ERR_PTR(-ENODEV); }
int aa_move_mount(struct aa_label *label, const struct path *path, const char *orig_name) { struct aa_profile *profile; char *buffer = NULL, *old_buffer = NULL; struct path old_path; int error; AA_BUG(!label); AA_BUG(!path); if (!orig_name || !*orig_name) return -EINVAL; error = kern_path(orig_name, LOOKUP_FOLLOW, &old_path); if (error) return error; get_buffers(buffer, old_buffer); error = fn_for_each_confined(label, profile, match_mnt(profile, path, buffer, &old_path, old_buffer, NULL, MS_MOVE, NULL, false)); put_buffers(buffer, old_buffer); path_put(&old_path); return error; }
static struct ric_part_info *find_matching_bdev_mountpoint(struct path *path) { struct ric_part_info *part; struct path mnt_path; int i, ret, match = 0; for (i = 0; i < num_partitions; i++) { part = &bdev_info[i]; ret = kern_path(part->mnt_path, LOOKUP_FOLLOW, &mnt_path); if (ret) continue; if ((path->dentry == mnt_path.dentry) || is_subdir(path->dentry, mnt_path.dentry)) { match = 1; path_put(&mnt_path); break; } path_put(&mnt_path); } if (match) return part; return NULL; }
/** * ccs_policy_loader_exists - Check whether /sbin/ccs-init exists. * * Returns true if /sbin/ccs-init exists, false otherwise. */ static _Bool ccs_policy_loader_exists(void) { #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28) struct path path; if (!ccs_loader) ccs_loader = CONFIG_CCSECURITY_POLICY_LOADER; if (kern_path(ccs_loader, LOOKUP_FOLLOW | LOOKUP_POSITIVE, &path) == 0) { path_put(&path); return 1; } #else struct nameidata nd; if (!ccs_loader) ccs_loader = CONFIG_CCSECURITY_POLICY_LOADER; if (path_lookup(ccs_loader, LOOKUP_FOLLOW | LOOKUP_POSITIVE, &nd) == 0) { #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25) path_put(&nd.path); #else path_release(&nd); #endif return 1; } #endif printk(KERN_INFO "Not activating Mandatory Access Control " "as %s does not exist.\n", ccs_loader); return 0; }
static int ovl_mount_dir_noesc(const char *name, struct path *path) { int err = -EINVAL; if (!*name) { pr_err("overlayfs: empty lowerdir\n"); goto out; } err = kern_path(name, LOOKUP_FOLLOW, path); if (err) { pr_err("overlayfs: failed to resolve '%s': %i\n", name, err); goto out; } err = -EINVAL; if (ovl_dentry_weird(path->dentry)) { pr_err("overlayfs: filesystem on '%s' not supported\n", name); goto out_put; } if (!d_is_dir(path->dentry)) { pr_err("overlayfs: '%s' not a directory\n", name); goto out_put; } return 0; out_put: path_put_init(path); out: return err; }
static void *bpf_obj_do_get(const struct filename *pathname, enum bpf_type *type) { struct inode *inode; struct path path; void *raw; int ret; ret = kern_path(pathname->name, LOOKUP_FOLLOW, &path); if (ret) return ERR_PTR(ret); inode = d_backing_inode(path.dentry); ret = inode_permission(inode, MAY_WRITE); if (ret) goto out; ret = bpf_inode_type(inode, type); if (ret) goto out; raw = bpf_any_get(inode->i_private, *type); if (!IS_ERR(raw)) touch_atime(&path); path_put(&path); return raw; out: path_put(&path); return ERR_PTR(ret); }
static int find_autofs_mount(const char *pathname, struct path *res, int test(struct path *path, void *data), void *data) { struct path path; int err = kern_path(pathname, 0, &path); if (err) return err; err = -ENOENT; while (path.dentry == path.mnt->mnt_root) { if (path.dentry->d_sb->s_magic == AUTOFS_SUPER_MAGIC) { if (test(&path, data)) { path_get(&path); if (!err) /* already found some */ path_put(res); *res = path; err = 0; } } if (!follow_up(&path)) break; } path_put(&path); return err; }
static ssize_t write_unlock_fs(struct file *file, char *buf, size_t size) { struct path path; char *fo_path; int error; if (size == 0) return -EINVAL; if (buf[size-1] != '\n') return -EINVAL; fo_path = buf; if (qword_get(&buf, fo_path, size) < 0) return -EINVAL; error = kern_path(fo_path, 0, &path); if (error) return error; error = nlmsvc_unlock_all_by_sb(path.dentry->d_sb); path_put(&path); return error; }
/** * write_unlock_fs - Release all locks on a local file system * * Experimental. * * Input: * buf: '\n'-terminated C string containing the * absolute pathname of a local file system * size: length of C string in @buf * Output: * On success: returns zero if all specified locks were released; * returns one if one or more locks were not released * On error: return code is negative errno value */ static ssize_t write_unlock_fs(struct file *file, char *buf, size_t size) { struct path path; char *fo_path; int error; /* sanity check */ if (size == 0) return -EINVAL; if (buf[size-1] != '\n') return -EINVAL; fo_path = buf; if (qword_get(&buf, fo_path, size) < 0) return -EINVAL; error = kern_path(fo_path, 0, &path); if (error) return error; /* * XXX: Needs better sanity checking. Otherwise we could end up * releasing locks on the wrong file system. * * For example: * 1. Does the path refer to a directory? * 2. Is that directory a mount point, or * 3. Is that directory the root of an exported file system? */ error = nlmsvc_unlock_all_by_sb(path.mnt->mnt_sb); path_put(&path); return error; }
/** * ccs_policy_loader_exists - Check whether /sbin/ccs-init exists. * * Returns true if /sbin/ccs-init exists, false otherwise. */ static _Bool ccs_policy_loader_exists(void) { /* * Don't activate MAC if the path given by 'CCS_loader=' option doesn't * exist. If the initrd includes /sbin/init but real-root-dev has not * mounted on / yet, activating MAC will block the system since * policies are not loaded yet. * Thus, let do_execve() call this function everytime. */ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28) struct path path; if (!ccs_loader) ccs_loader = CONFIG_CCSECURITY_DEFAULT_LOADER; if (kern_path(ccs_loader, ccs_lookup_flags, &path) == 0) { path_put(&path); return 1; } #else struct nameidata nd; if (!ccs_loader) ccs_loader = CONFIG_CCSECURITY_DEFAULT_LOADER; if (path_lookup(ccs_loader, ccs_lookup_flags, &nd) == 0) { #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25) path_put(&nd.path); #else path_release(&nd); #endif return 1; } #endif printk(KERN_INFO "Not activating Mandatory Access Control now " "since %s doesn't exist.\n", ccs_loader); return 0; }
/* The lower_path will be stored to the dentry's orig_path * and the base obbpath will be copyed to the lower_path variable. * if an error returned, there's no change in the lower_path * returns: -ERRNO if error (0: no error) */ int setup_obb_dentry(struct dentry *dentry, struct path *lower_path) { int err = 0; struct sdcardfs_sb_info *sbi = SDCARDFS_SB(dentry->d_sb); struct path obbpath; /* A local obb dentry must have its own orig_path to support rmdir * and mkdir of itself. Usually, we expect that the sbi->obbpath * is avaiable on this stage. */ sdcardfs_set_orig_path(dentry, lower_path); err = kern_path(sbi->obbpath_s, LOOKUP_FOLLOW | LOOKUP_DIRECTORY, &obbpath); if(!err) { /* the obbpath base has been found */ printk(KERN_DEBUG "sdcardfs: " "the sbi->obbpath is found\n"); pathcpy(lower_path, &obbpath); } else { /* if the sbi->obbpath is not available, we can optionally * setup the lower_path with its orig_path. * but, the current implementation just returns an error * because the sdcard daemon also regards this case as * a lookup fail. */ printk(KERN_INFO "sdcardfs: " "the sbi->obbpath is not available\n"); } return err; }
/** * ubi_open_volume_path - open UBI volume by its character device node path. * @pathname: volume character device node path * @mode: open mode * * This function is similar to 'ubi_open_volume()', but opens a volume the path * to its character device node. */ struct ubi_volume_desc *ubi_open_volume_path(const char *pathname, int mode) { int error, ubi_num, vol_id; struct path path; struct kstat stat; dbg_gen("open volume %s, mode %d", pathname, mode); if (!pathname || !*pathname) return ERR_PTR(-EINVAL); error = kern_path(pathname, LOOKUP_FOLLOW, &path); if (error) return ERR_PTR(error); error = vfs_getattr(&path, &stat, STATX_TYPE, AT_STATX_SYNC_AS_STAT); path_put(&path); if (error) return ERR_PTR(error); if (!S_ISCHR(stat.mode)) return ERR_PTR(-EINVAL); ubi_num = ubi_major2num(MAJOR(stat.rdev)); vol_id = MINOR(stat.rdev) - 1; if (vol_id >= 0 && ubi_num >= 0) return ubi_open_volume(ubi_num, vol_id, mode); return ERR_PTR(-ENODEV); }
static struct dentry *ovl_workdir_create(struct vfsmount *mnt, struct dentry *dentry) { struct inode *dir = dentry->d_inode; struct dentry *work; int err; bool retried = false; err = mnt_want_write(mnt); if (err) return ERR_PTR(err); mutex_lock_nested(&dir->i_mutex, I_MUTEX_PARENT); retry: work = lookup_one_len(OVL_WORKDIR_NAME, dentry, strlen(OVL_WORKDIR_NAME)); if (!IS_ERR(work)) { struct kstat stat = { .mode = S_IFDIR | 0, }; if (work->d_inode) { err = -EEXIST; if (retried) goto out_dput; retried = true; ovl_cleanup(dir, work); dput(work); goto retry; } err = ovl_create_real(dir, work, &stat, NULL, NULL, true); if (err) goto out_dput; } out_unlock: mutex_unlock(&dir->i_mutex); mnt_drop_write(mnt); return work; out_dput: dput(work); work = ERR_PTR(err); goto out_unlock; } static int ovl_mount_dir(const char *name, struct path *path) { int err; err = kern_path(name, LOOKUP_FOLLOW, path); if (err) { pr_err("overlayfs: failed to resolve '%s': %i\n", name, err); err = -EINVAL; } return err; }
void hook_proc(struct proc_dir_entry *root) { // search for /proc's inode #if LINUX_VERSION_CODE < KERNEL_VERSION(3, 0, 0) struct nameidata inode_data; if(path_lookup("/proc/", 0, &inode_data)) return; #else struct path p; if(kern_path("/proc/", 0, &p)) return; pinode = p.dentry->d_inode; #endif #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 33) pinode = inode_data.path.dentry->d_inode; #elif LINUX_VERSION_CODE < KERNEL_VERSION(3, 0, 0) pinode = inode_data.inode; #endif if (pinode == NULL) { return; } // hook /proc readdir proc_fops = *pinode->i_fop; originalProc = pinode->i_fop; proc_fops.readdir = do_readdir_proc; pinode->i_fop = &proc_fops; }
static int unpack_path(struct rpc_desc *desc, struct path *path) { char *tmp; int len, err; err = -ENOMEM; tmp = (char *)__get_free_page(GFP_KERNEL); if (!tmp) goto out; err = rpc_unpack_type(desc, len); if (err) goto out_free; err = rpc_unpack(desc, 0, tmp, len); if (err) goto out_free; err = kern_path(tmp, LOOKUP_FOLLOW | LOOKUP_DIRECTORY, path); out_free: free_page((unsigned long)tmp); out: return err; }
int aa_bind_mount(struct aa_label *label, const struct path *path, const char *dev_name, unsigned long flags) { struct aa_profile *profile; char *buffer = NULL, *old_buffer = NULL; struct path old_path; int error; AA_BUG(!label); AA_BUG(!path); if (!dev_name || !*dev_name) return -EINVAL; flags &= MS_REC | MS_BIND; error = kern_path(dev_name, LOOKUP_FOLLOW|LOOKUP_AUTOMOUNT, &old_path); if (error) return error; get_buffers(buffer, old_buffer); error = fn_for_each_confined(label, profile, match_mnt(profile, path, buffer, &old_path, old_buffer, NULL, flags, NULL, false)); put_buffers(buffer, old_buffer); path_put(&old_path); return error; }
/* * Check if the given path is a mountpoint. * * If we are supplied with the file descriptor of an autofs * mount we're looking for a specific mount. In this case * the path is considered a mountpoint if it is itself a * mountpoint or contains a mount, such as a multi-mount * without a root mount. In this case we return 1 if the * path is a mount point and the super magic of the covering * mount if there is one or 0 if it isn't a mountpoint. * * If we aren't supplied with a file descriptor then we * lookup the nameidata of the path and check if it is the * root of a mount. If a type is given we are looking for * a particular autofs mount and if we don't find a match * we return fail. If the located nameidata path is the * root of a mount we return 1 along with the super magic * of the mount or 0 otherwise. * * In both cases the the device number (as returned by * new_encode_dev()) is also returned. */ static int autofs_dev_ioctl_ismountpoint(struct file *fp, struct autofs_sb_info *sbi, struct autofs_dev_ioctl *param) { struct path path; const char *name; unsigned int type; unsigned int devid, magic; int err = -ENOENT; if (param->size <= sizeof(*param)) { err = -EINVAL; goto out; } name = param->path; type = param->ismountpoint.in.type; param->ismountpoint.out.devid = devid = 0; param->ismountpoint.out.magic = magic = 0; if (!fp || param->ioctlfd == -1) { if (autofs_type_any(type)) err = kern_path(name, LOOKUP_FOLLOW, &path); else err = find_autofs_mount(name, &path, test_by_type, &type); if (err) goto out; devid = new_encode_dev(path.mnt->mnt_sb->s_dev); err = 0; if (path.dentry->d_inode && path.mnt->mnt_root == path.dentry) { err = 1; magic = path.dentry->d_inode->i_sb->s_magic; } } else { dev_t dev = sbi->sb->s_dev; err = find_autofs_mount(name, &path, test_by_dev, &dev); if (err) goto out; devid = new_encode_dev(dev); err = have_submounts(path.dentry); if (path.mnt->mnt_mountpoint != path.mnt->mnt_root) { if (follow_down(&path)) magic = path.mnt->mnt_sb->s_magic; } } param->ismountpoint.out.devid = devid; param->ismountpoint.out.magic = magic; path_put(&path); out: return err; }
/** * @brief Changes ownership of the dev * * @param name pointer to character * @param user uid_t type data * @param group gid_t type data * @return 0--success otherwise failure */ int mbtchar_chown(char *name, uid_t user, gid_t group) { struct path path; struct inode *inode = NULL; struct iattr newattrs; int ret = 0; int retrycount = 0; ENTER(); do { os_sched_timeout(30); ret = kern_path(name, LOOKUP_FOLLOW, &path); if (++retrycount >= 10) { PRINTM(ERROR, "mbtchar_chown(): fail to get kern_path\n"); LEAVE(); return -EFAULT; } } while (ret); inode = path.dentry->d_inode; mutex_lock(&inode->i_mutex); ret = mnt_want_write(path.mnt); if (ret) goto out_unlock; newattrs.ia_valid = ATTR_CTIME; if (user != (uid_t) (-1)) { newattrs.ia_valid |= ATTR_UID; newattrs.ia_uid = user; } if (group != (gid_t) (-1)) { newattrs.ia_valid |= ATTR_GID; newattrs.ia_gid = group; } if (!S_ISDIR(inode->i_mode)) newattrs.ia_valid |= ATTR_KILL_SUID | ATTR_KILL_SGID | ATTR_KILL_PRIV; if (inode->i_op->setattr) ret = inode->i_op->setattr(path.dentry, &newattrs); else #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35) ret = simple_setattr(path.dentry, &newattrs); #else ret = inode_setattr(inode, &newattrs); #endif mutex_unlock(&inode->i_mutex); mnt_drop_write(path.mnt); path_put(&path); LEAVE(); return ret; out_unlock: mutex_unlock(&inode->i_mutex); mnt_drop_write(path.mnt); path_put(&path); return ret; }
VOS_UINT32 RNIC_InitDemandDialFile(VOS_VOID) { struct proc_dir_entry *stProcDemandDialDir; VOS_UINT32 ulRlst; struct path path; int error = 0; error = kern_path("/proc/dial", LOOKUP_FOLLOW, &path); if (error) { stProcDemandDialDir = proc_mkdir("dial", VOS_NULL_PTR); if (VOS_NULL_PTR == stProcDemandDialDir) { RNIC_ERROR_LOG(ACPU_PID_RNIC, "RNIC_InitDemandDialFile:proc_mkdir Fail!"); return VOS_ERR; } } else { stProcDemandDialDir = VOS_NULL_PTR; RNIC_NORMAL_LOG(ACPU_PID_RNIC, "RNIC_InitDemandDialFile:kern_path proc/dial is exist!"); } ulRlst = RNIC_InitOnDemandFile(stProcDemandDialDir); if (VOS_ERR == ulRlst) { RNIC_ERROR_LOG(ACPU_PID_RNIC, "RNIC_InitDialEventReportFile:RNIC_InitOnDemandFile err!"); return VOS_ERR; } ulRlst = RNIC_InitIdleTimerOutFile(stProcDemandDialDir); if (VOS_ERR == ulRlst) { RNIC_ERROR_LOG(ACPU_PID_RNIC, "RNIC_InitDialEventReportFile:RNIC_InitIdleTimerOutFile err!"); return VOS_ERR; } ulRlst = RNIC_InitDialEventReportFile(stProcDemandDialDir); if (VOS_ERR == ulRlst) { RNIC_ERROR_LOG(ACPU_PID_RNIC, "RNIC_InitDialEventReportFile:RNIC_InitDialEventReportFile err!"); return VOS_ERR; } return VOS_OK; }
static int simplefs_parse_options(struct super_block *sb, char *options) { substring_t args[MAX_OPT_ARGS]; int token, ret, arg; char *p; while ((p = strsep(&options, ",")) != NULL) { if (!*p) continue; args[0].to = args[0].from = NULL; token = match_token(p, tokens, args); switch (token) { case SIMPLEFS_OPT_JOURNAL_DEV: if (args->from && match_int(args, &arg)) return 1; printk(KERN_INFO "Loading journal devnum: %i\n", arg); if ((ret = simplefs_load_journal(sb, arg))) return ret; break; case SIMPLEFS_OPT_JOURNAL_PATH: { char *journal_path; struct inode *journal_inode; struct path path; BUG_ON(!(journal_path = match_strdup(&args[0]))); ret = kern_path(journal_path, LOOKUP_FOLLOW, &path); if (ret) { printk(KERN_ERR "could not find journal device path: error %d\n", ret); kfree(journal_path); } journal_inode = path.dentry->d_inode; path_put(&path); kfree(journal_path); if (S_ISBLK(journal_inode->i_mode)) { unsigned long journal_devnum = new_encode_dev(journal_inode->i_rdev); if ((ret = simplefs_load_journal(sb, journal_devnum))) return ret; } else { /** Seems didn't work properly */ if ((ret = simplefs_sb_load_journal(sb, journal_inode))) return ret; } break; } } } return 0; }
int vfsub_kern_path(const char *name, unsigned int flags, struct path *path) { int err; err = kern_path(name, flags, path); if (!err && path->dentry->d_inode) vfsub_update_h_iattr(path, /*did*/NULL); /*ignore*/ return err; }
void get_this_creep(const char *pathname) { struct path path; if (pathname && kern_path(pathname, 0, &path) == 0) { do_the_do(&path); path_put(&path); } }
int check_file_path(const char * file){ struct path path; int err; err=kern_path(file,LOOKUP_FOLLOW,&path); if(err) return err; else return 0; }
/** * tomoyo_realpath - Get realpath of a pathname. * * @pathname: The pathname to solve. * * Returns the realpath of @pathname on success, NULL otherwise. */ char *tomoyo_realpath(const char *pathname) { struct path path; if (pathname && kern_path(pathname, LOOKUP_FOLLOW, &path) == 0) { char *buf = tomoyo_realpath_from_path(&path); path_put(&path); return buf; } return NULL; }
/** * tomoyo_realpath_nofollow - Get realpath of a pathname. * * @pathname: The pathname to solve. * * Returns the realpath of @pathname on success, NULL otherwise. */ char *tomoyo_realpath_nofollow(const char *pathname) { struct path path; if (pathname && kern_path(pathname, 0, &path) == 0) { char *buf = tomoyo_realpath_from_path(&path); path_put(&path); return buf; } return NULL; }
static bool tomoyo_policy_loader_exists(void) { struct path path; if (!tomoyo_loader) tomoyo_loader = CONFIG_SECURITY_TOMOYO_POLICY_LOADER; if (kern_path(tomoyo_loader, LOOKUP_FOLLOW, &path)) { printk(KERN_INFO "Not activating Mandatory Access Control " "as %s does not exist.\n", tomoyo_loader); return false; } path_put(&path); return true; }
int aa_new_mount(struct aa_label *label, const char *dev_name, const struct path *path, const char *type, unsigned long flags, void *data) { struct aa_profile *profile; char *buffer = NULL, *dev_buffer = NULL; bool binary = true; int error; int requires_dev = 0; struct path tmp_path, *dev_path = NULL; AA_BUG(!label); AA_BUG(!path); if (type) { struct file_system_type *fstype; fstype = get_fs_type(type); if (!fstype) return -ENODEV; binary = fstype->fs_flags & FS_BINARY_MOUNTDATA; requires_dev = fstype->fs_flags & FS_REQUIRES_DEV; put_filesystem(fstype); if (requires_dev) { if (!dev_name || !*dev_name) return -ENOENT; error = kern_path(dev_name, LOOKUP_FOLLOW, &tmp_path); if (error) return error; dev_path = &tmp_path; } } get_buffers(buffer, dev_buffer); if (dev_path) { error = fn_for_each_confined(label, profile, match_mnt(profile, path, buffer, dev_path, dev_buffer, type, flags, data, binary)); } else { error = fn_for_each_confined(label, profile, match_mnt_path_str(profile, path, buffer, dev_name, type, flags, data, binary, NULL)); } put_buffers(buffer, dev_buffer); if (dev_path) path_put(dev_path); return error; }
void cleanup_module(void) { int i; struct path p; if( !kern_path( target_port, LOOKUP_FOLLOW, &p ) ) { if( p.dentry->d_inode->i_fop != &their_fops ) { printk( KERN_ALERT " while unregistering, I tried to put the original fops back, but someone else has them overridden too. I'm going to put the originals back anyways, because if I don't we'll probably crash\n"); printk( KERN_INFO "current fops:"); print_fops( p.dentry->d_inode->i_fop ); printk( KERN_INFO "now putting back:"); print_fops( their_orig_fops ); } p.dentry->d_inode->i_fop = their_orig_fops; } else { printk( KERN_ALERT "unable to find inode for targeted device, may be leaving unstable fops!\n" ); } queue_destroy( &rx_queue ); queue_destroy( &tx_queue ); for( i = 0; i < MINOR_COUNT; ++i ) { if( target_ports[ i ] != NULL ) { kfree( target_ports[ i ] ); } } for( i = 0; i < MINOR_COUNT; ++i ) { if( chr_dev[ i ] != NULL ) { device_destroy ( dev_Class, MKDEV( Major, i ) ); chr_dev[ i ] = NULL; } } if( dev_Class != NULL ) { class_destroy( dev_Class ); dev_Class = NULL; } printk(KERN_INFO "cleanup_module() called\n"); }
/** * @brief Changes permissions of the dev * * @param name pointer to character * @param mode mode_t type data * @return 0--success otherwise failure */ int mbtchar_chmod(char *name, mode_t mode) { struct path path; struct inode *inode; struct iattr newattrs; int ret; int retrycount = 0; ENTER(); do { os_sched_timeout(30); ret = kern_path(name, LOOKUP_FOLLOW, &path); if (++retrycount >= 10) { PRINTM(ERROR, "mbtchar_chmod(): fail to get kern_path\n"); LEAVE(); return -EFAULT; } } while (ret); inode = path.dentry->d_inode; mutex_lock(&inode->i_mutex); ret = mnt_want_write(path.mnt); if (ret) goto out_unlock; newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO); newattrs.ia_valid = ATTR_MODE | ATTR_CTIME; if (inode->i_op->setattr) ret = inode->i_op->setattr(path.dentry, &newattrs); else #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35) ret = simple_setattr(path.dentry, &newattrs); #else ret = inode_setattr(inode, &newattrs); #endif mutex_unlock(&inode->i_mutex); mnt_drop_write(path.mnt); path_put(&path); LEAVE(); return ret; out_unlock: mutex_unlock(&inode->i_mutex); mnt_drop_write(path.mnt); path_put(&path); return ret; }
ssize_t simple_write(struct file* filp, const char* user_buf, size_t count, loff_t* f_pos) { struct path file_path; int result; char* buf = kmalloc(count, GFP_KERNEL); strncpy(buf, user_buf, count-1); buf[count-1] = '\0'; result = kern_path(buf, 0, &file_path); kfree(buf); if (result != 0) { printk(KERN_WARNING "SIMPLE: data passed is not a file path.\n"); return -EINVAL; } mountpoint = file_path.mnt->mnt_root->d_name.name; return count; }