Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  * symlink.c - operations for configfs symlinks.
0004  *
0005  * Based on sysfs:
0006  *  sysfs is Copyright (C) 2001, 2002, 2003 Patrick Mochel
0007  *
0008  * configfs Copyright (C) 2005 Oracle.  All rights reserved.
0009  */
0010 
0011 #include <linux/fs.h>
0012 #include <linux/module.h>
0013 #include <linux/namei.h>
0014 #include <linux/slab.h>
0015 
0016 #include <linux/configfs.h>
0017 #include "configfs_internal.h"
0018 
0019 /* Protects attachments of new symlinks */
0020 DEFINE_MUTEX(configfs_symlink_mutex);
0021 
0022 static int item_depth(struct config_item * item)
0023 {
0024     struct config_item * p = item;
0025     int depth = 0;
0026     do { depth++; } while ((p = p->ci_parent) && !configfs_is_root(p));
0027     return depth;
0028 }
0029 
0030 static int item_path_length(struct config_item * item)
0031 {
0032     struct config_item * p = item;
0033     int length = 1;
0034     do {
0035         length += strlen(config_item_name(p)) + 1;
0036         p = p->ci_parent;
0037     } while (p && !configfs_is_root(p));
0038     return length;
0039 }
0040 
0041 static void fill_item_path(struct config_item * item, char * buffer, int length)
0042 {
0043     struct config_item * p;
0044 
0045     --length;
0046     for (p = item; p && !configfs_is_root(p); p = p->ci_parent) {
0047         int cur = strlen(config_item_name(p));
0048 
0049         /* back up enough to print this bus id with '/' */
0050         length -= cur;
0051         memcpy(buffer + length, config_item_name(p), cur);
0052         *(buffer + --length) = '/';
0053     }
0054 }
0055 
0056 static int configfs_get_target_path(struct config_item *item,
0057         struct config_item *target, char *path)
0058 {
0059     int depth, size;
0060     char *s;
0061 
0062     depth = item_depth(item);
0063     size = item_path_length(target) + depth * 3 - 1;
0064     if (size > PATH_MAX)
0065         return -ENAMETOOLONG;
0066 
0067     pr_debug("%s: depth = %d, size = %d\n", __func__, depth, size);
0068 
0069     for (s = path; depth--; s += 3)
0070         strcpy(s,"../");
0071 
0072     fill_item_path(target, path, size);
0073     pr_debug("%s: path = '%s'\n", __func__, path);
0074     return 0;
0075 }
0076 
0077 static int create_link(struct config_item *parent_item,
0078                struct config_item *item,
0079                struct dentry *dentry)
0080 {
0081     struct configfs_dirent *target_sd = item->ci_dentry->d_fsdata;
0082     char *body;
0083     int ret;
0084 
0085     if (!configfs_dirent_is_ready(target_sd))
0086         return -ENOENT;
0087 
0088     body = kzalloc(PAGE_SIZE, GFP_KERNEL);
0089     if (!body)
0090         return -ENOMEM;
0091 
0092     configfs_get(target_sd);
0093     spin_lock(&configfs_dirent_lock);
0094     if (target_sd->s_type & CONFIGFS_USET_DROPPING) {
0095         spin_unlock(&configfs_dirent_lock);
0096         configfs_put(target_sd);
0097         kfree(body);
0098         return -ENOENT;
0099     }
0100     target_sd->s_links++;
0101     spin_unlock(&configfs_dirent_lock);
0102     ret = configfs_get_target_path(parent_item, item, body);
0103     if (!ret)
0104         ret = configfs_create_link(target_sd, parent_item->ci_dentry,
0105                        dentry, body);
0106     if (ret) {
0107         spin_lock(&configfs_dirent_lock);
0108         target_sd->s_links--;
0109         spin_unlock(&configfs_dirent_lock);
0110         configfs_put(target_sd);
0111         kfree(body);
0112     }
0113     return ret;
0114 }
0115 
0116 
0117 static int get_target(const char *symname, struct path *path,
0118               struct config_item **target, struct super_block *sb)
0119 {
0120     int ret;
0121 
0122     ret = kern_path(symname, LOOKUP_FOLLOW|LOOKUP_DIRECTORY, path);
0123     if (!ret) {
0124         if (path->dentry->d_sb == sb) {
0125             *target = configfs_get_config_item(path->dentry);
0126             if (!*target) {
0127                 ret = -ENOENT;
0128                 path_put(path);
0129             }
0130         } else {
0131             ret = -EPERM;
0132             path_put(path);
0133         }
0134     }
0135 
0136     return ret;
0137 }
0138 
0139 
0140 int configfs_symlink(struct user_namespace *mnt_userns, struct inode *dir,
0141              struct dentry *dentry, const char *symname)
0142 {
0143     int ret;
0144     struct path path;
0145     struct configfs_dirent *sd;
0146     struct config_item *parent_item;
0147     struct config_item *target_item = NULL;
0148     const struct config_item_type *type;
0149 
0150     sd = dentry->d_parent->d_fsdata;
0151     /*
0152      * Fake invisibility if dir belongs to a group/default groups hierarchy
0153      * being attached
0154      */
0155     if (!configfs_dirent_is_ready(sd))
0156         return -ENOENT;
0157 
0158     parent_item = configfs_get_config_item(dentry->d_parent);
0159     type = parent_item->ci_type;
0160 
0161     ret = -EPERM;
0162     if (!type || !type->ct_item_ops ||
0163         !type->ct_item_ops->allow_link)
0164         goto out_put;
0165 
0166     /*
0167      * This is really sick.  What they wanted was a hybrid of
0168      * link(2) and symlink(2) - they wanted the target resolved
0169      * at syscall time (as link(2) would've done), be a directory
0170      * (which link(2) would've refused to do) *AND* be a deep
0171      * fucking magic, making the target busy from rmdir POV.
0172      * symlink(2) is nothing of that sort, and the locking it
0173      * gets matches the normal symlink(2) semantics.  Without
0174      * attempts to resolve the target (which might very well
0175      * not even exist yet) done prior to locking the parent
0176      * directory.  This perversion, OTOH, needs to resolve
0177      * the target, which would lead to obvious deadlocks if
0178      * attempted with any directories locked.
0179      *
0180      * Unfortunately, that garbage is userland ABI and we should've
0181      * said "no" back in 2005.  Too late now, so we get to
0182      * play very ugly games with locking.
0183      *
0184      * Try *ANYTHING* of that sort in new code, and you will
0185      * really regret it.  Just ask yourself - what could a BOFH
0186      * do to me and do I want to find it out first-hand?
0187      *
0188      *  AV, a thoroughly annoyed bastard.
0189      */
0190     inode_unlock(dir);
0191     ret = get_target(symname, &path, &target_item, dentry->d_sb);
0192     inode_lock(dir);
0193     if (ret)
0194         goto out_put;
0195 
0196     if (dentry->d_inode || d_unhashed(dentry))
0197         ret = -EEXIST;
0198     else
0199         ret = inode_permission(&init_user_ns, dir,
0200                        MAY_WRITE | MAY_EXEC);
0201     if (!ret)
0202         ret = type->ct_item_ops->allow_link(parent_item, target_item);
0203     if (!ret) {
0204         mutex_lock(&configfs_symlink_mutex);
0205         ret = create_link(parent_item, target_item, dentry);
0206         mutex_unlock(&configfs_symlink_mutex);
0207         if (ret && type->ct_item_ops->drop_link)
0208             type->ct_item_ops->drop_link(parent_item,
0209                              target_item);
0210     }
0211 
0212     config_item_put(target_item);
0213     path_put(&path);
0214 
0215 out_put:
0216     config_item_put(parent_item);
0217     return ret;
0218 }
0219 
0220 int configfs_unlink(struct inode *dir, struct dentry *dentry)
0221 {
0222     struct configfs_dirent *sd = dentry->d_fsdata, *target_sd;
0223     struct config_item *parent_item;
0224     const struct config_item_type *type;
0225     int ret;
0226 
0227     ret = -EPERM;  /* What lack-of-symlink returns */
0228     if (!(sd->s_type & CONFIGFS_ITEM_LINK))
0229         goto out;
0230 
0231     target_sd = sd->s_element;
0232 
0233     parent_item = configfs_get_config_item(dentry->d_parent);
0234     type = parent_item->ci_type;
0235 
0236     spin_lock(&configfs_dirent_lock);
0237     list_del_init(&sd->s_sibling);
0238     spin_unlock(&configfs_dirent_lock);
0239     configfs_drop_dentry(sd, dentry->d_parent);
0240     dput(dentry);
0241     configfs_put(sd);
0242 
0243     /*
0244      * drop_link() must be called before
0245      * decrementing target's ->s_links, so that the order of
0246      * drop_link(this, target) and drop_item(target) is preserved.
0247      */
0248     if (type && type->ct_item_ops &&
0249         type->ct_item_ops->drop_link)
0250         type->ct_item_ops->drop_link(parent_item,
0251                            target_sd->s_element);
0252 
0253     spin_lock(&configfs_dirent_lock);
0254     target_sd->s_links--;
0255     spin_unlock(&configfs_dirent_lock);
0256     configfs_put(target_sd);
0257 
0258     config_item_put(parent_item);
0259 
0260     ret = 0;
0261 
0262 out:
0263     return ret;
0264 }
0265 
0266 const struct inode_operations configfs_symlink_inode_operations = {
0267     .get_link = simple_get_link,
0268     .setattr = configfs_setattr,
0269 };
0270