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