1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* -*- mode: c; c-basic-offset: 8; -*- 3 * vim: noexpandtab sw=8 ts=8 sts=0: 4 * 5 * symlink.c - operations for configfs symlinks. 6 * 7 * Based on sysfs: 8 * sysfs is Copyright (C) 2001, 2002, 2003 Patrick Mochel 9 * 10 * configfs Copyright (C) 2005 Oracle. All rights reserved. 11 */ 12 13 #include <linux/fs.h> 14 #include <linux/module.h> 15 #include <linux/namei.h> 16 #include <linux/slab.h> 17 18 #include <linux/configfs.h> 19 #include "configfs_internal.h" 20 21 /* Protects attachments of new symlinks */ 22 DEFINE_MUTEX(configfs_symlink_mutex); 23 24 static int item_depth(struct config_item * item) 25 { 26 struct config_item * p = item; 27 int depth = 0; 28 do { depth++; } while ((p = p->ci_parent) && !configfs_is_root(p)); 29 return depth; 30 } 31 32 static int item_path_length(struct config_item * item) 33 { 34 struct config_item * p = item; 35 int length = 1; 36 do { 37 length += strlen(config_item_name(p)) + 1; 38 p = p->ci_parent; 39 } while (p && !configfs_is_root(p)); 40 return length; 41 } 42 43 static void fill_item_path(struct config_item * item, char * buffer, int length) 44 { 45 struct config_item * p; 46 47 --length; 48 for (p = item; p && !configfs_is_root(p); p = p->ci_parent) { 49 int cur = strlen(config_item_name(p)); 50 51 /* back up enough to print this bus id with '/' */ 52 length -= cur; 53 memcpy(buffer + length, config_item_name(p), cur); 54 *(buffer + --length) = '/'; 55 } 56 } 57 58 static int configfs_get_target_path(struct config_item *item, 59 struct config_item *target, char *path) 60 { 61 int depth, size; 62 char *s; 63 64 depth = item_depth(item); 65 size = item_path_length(target) + depth * 3 - 1; 66 if (size > PATH_MAX) 67 return -ENAMETOOLONG; 68 69 pr_debug("%s: depth = %d, size = %d\n", __func__, depth, size); 70 71 for (s = path; depth--; s += 3) 72 strcpy(s,"../"); 73 74 fill_item_path(target, path, size); 75 pr_debug("%s: path = '%s'\n", __func__, path); 76 return 0; 77 } 78 79 static int create_link(struct config_item *parent_item, 80 struct config_item *item, 81 struct dentry *dentry) 82 { 83 struct configfs_dirent *target_sd = item->ci_dentry->d_fsdata; 84 char *body; 85 int ret; 86 87 if (!configfs_dirent_is_ready(target_sd)) 88 return -ENOENT; 89 90 body = kzalloc(PAGE_SIZE, GFP_KERNEL); 91 if (!body) 92 return -ENOMEM; 93 94 configfs_get(target_sd); 95 spin_lock(&configfs_dirent_lock); 96 if (target_sd->s_type & CONFIGFS_USET_DROPPING) { 97 spin_unlock(&configfs_dirent_lock); 98 configfs_put(target_sd); 99 kfree(body); 100 return -ENOENT; 101 } 102 target_sd->s_links++; 103 spin_unlock(&configfs_dirent_lock); 104 ret = configfs_get_target_path(item, item, body); 105 if (!ret) 106 ret = configfs_create_link(target_sd, parent_item->ci_dentry, 107 dentry, body); 108 if (ret) { 109 spin_lock(&configfs_dirent_lock); 110 target_sd->s_links--; 111 spin_unlock(&configfs_dirent_lock); 112 configfs_put(target_sd); 113 kfree(body); 114 } 115 return ret; 116 } 117 118 119 static int get_target(const char *symname, struct path *path, 120 struct config_item **target, struct super_block *sb) 121 { 122 int ret; 123 124 ret = kern_path(symname, LOOKUP_FOLLOW|LOOKUP_DIRECTORY, path); 125 if (!ret) { 126 if (path->dentry->d_sb == sb) { 127 *target = configfs_get_config_item(path->dentry); 128 if (!*target) { 129 ret = -ENOENT; 130 path_put(path); 131 } 132 } else { 133 ret = -EPERM; 134 path_put(path); 135 } 136 } 137 138 return ret; 139 } 140 141 142 int configfs_symlink(struct inode *dir, struct dentry *dentry, const char *symname) 143 { 144 int ret; 145 struct path path; 146 struct configfs_dirent *sd; 147 struct config_item *parent_item; 148 struct config_item *target_item = NULL; 149 const struct config_item_type *type; 150 151 sd = dentry->d_parent->d_fsdata; 152 /* 153 * Fake invisibility if dir belongs to a group/default groups hierarchy 154 * being attached 155 */ 156 if (!configfs_dirent_is_ready(sd)) 157 return -ENOENT; 158 159 parent_item = configfs_get_config_item(dentry->d_parent); 160 type = parent_item->ci_type; 161 162 ret = -EPERM; 163 if (!type || !type->ct_item_ops || 164 !type->ct_item_ops->allow_link) 165 goto out_put; 166 167 /* 168 * This is really sick. What they wanted was a hybrid of 169 * link(2) and symlink(2) - they wanted the target resolved 170 * at syscall time (as link(2) would've done), be a directory 171 * (which link(2) would've refused to do) *AND* be a deep 172 * fucking magic, making the target busy from rmdir POV. 173 * symlink(2) is nothing of that sort, and the locking it 174 * gets matches the normal symlink(2) semantics. Without 175 * attempts to resolve the target (which might very well 176 * not even exist yet) done prior to locking the parent 177 * directory. This perversion, OTOH, needs to resolve 178 * the target, which would lead to obvious deadlocks if 179 * attempted with any directories locked. 180 * 181 * Unfortunately, that garbage is userland ABI and we should've 182 * said "no" back in 2005. Too late now, so we get to 183 * play very ugly games with locking. 184 * 185 * Try *ANYTHING* of that sort in new code, and you will 186 * really regret it. Just ask yourself - what could a BOFH 187 * do to me and do I want to find it out first-hand? 188 * 189 * AV, a thoroughly annoyed bastard. 190 */ 191 inode_unlock(dir); 192 ret = get_target(symname, &path, &target_item, dentry->d_sb); 193 inode_lock(dir); 194 if (ret) 195 goto out_put; 196 197 if (dentry->d_inode || d_unhashed(dentry)) 198 ret = -EEXIST; 199 else 200 ret = inode_permission(dir, MAY_WRITE | MAY_EXEC); 201 if (!ret) 202 ret = type->ct_item_ops->allow_link(parent_item, target_item); 203 if (!ret) { 204 mutex_lock(&configfs_symlink_mutex); 205 ret = create_link(parent_item, target_item, dentry); 206 mutex_unlock(&configfs_symlink_mutex); 207 if (ret && type->ct_item_ops->drop_link) 208 type->ct_item_ops->drop_link(parent_item, 209 target_item); 210 } 211 212 config_item_put(target_item); 213 path_put(&path); 214 215 out_put: 216 config_item_put(parent_item); 217 return ret; 218 } 219 220 int configfs_unlink(struct inode *dir, struct dentry *dentry) 221 { 222 struct configfs_dirent *sd = dentry->d_fsdata, *target_sd; 223 struct config_item *parent_item; 224 const struct config_item_type *type; 225 int ret; 226 227 ret = -EPERM; /* What lack-of-symlink returns */ 228 if (!(sd->s_type & CONFIGFS_ITEM_LINK)) 229 goto out; 230 231 target_sd = sd->s_element; 232 233 parent_item = configfs_get_config_item(dentry->d_parent); 234 type = parent_item->ci_type; 235 236 spin_lock(&configfs_dirent_lock); 237 list_del_init(&sd->s_sibling); 238 spin_unlock(&configfs_dirent_lock); 239 configfs_drop_dentry(sd, dentry->d_parent); 240 dput(dentry); 241 configfs_put(sd); 242 243 /* 244 * drop_link() must be called before 245 * decrementing target's ->s_links, so that the order of 246 * drop_link(this, target) and drop_item(target) is preserved. 247 */ 248 if (type && type->ct_item_ops && 249 type->ct_item_ops->drop_link) 250 type->ct_item_ops->drop_link(parent_item, 251 target_sd->s_element); 252 253 spin_lock(&configfs_dirent_lock); 254 target_sd->s_links--; 255 spin_unlock(&configfs_dirent_lock); 256 configfs_put(target_sd); 257 258 config_item_put(parent_item); 259 260 ret = 0; 261 262 out: 263 return ret; 264 } 265 266 const struct inode_operations configfs_symlink_inode_operations = { 267 .get_link = simple_get_link, 268 .setattr = configfs_setattr, 269 }; 270 271