1 /* 2 * fs/sysfs/symlink.c - sysfs symlink implementation 3 * 4 * Copyright (c) 2001-3 Patrick Mochel 5 * Copyright (c) 2007 SUSE Linux Products GmbH 6 * Copyright (c) 2007 Tejun Heo <teheo@suse.de> 7 * 8 * This file is released under the GPLv2. 9 * 10 * Please see Documentation/filesystems/sysfs.txt for more information. 11 */ 12 13 #include <linux/fs.h> 14 #include <linux/gfp.h> 15 #include <linux/mount.h> 16 #include <linux/module.h> 17 #include <linux/kobject.h> 18 #include <linux/namei.h> 19 #include <linux/mutex.h> 20 #include <linux/security.h> 21 22 #include "sysfs.h" 23 24 /** 25 * kernfs_create_link - create a symlink 26 * @parent: directory to create the symlink in 27 * @name: name of the symlink 28 * @target: target node for the symlink to point to 29 * 30 * Returns the created node on success, ERR_PTR() value on error. 31 */ 32 struct sysfs_dirent *kernfs_create_link(struct sysfs_dirent *parent, 33 const char *name, 34 struct sysfs_dirent *target) 35 { 36 struct sysfs_dirent *sd; 37 struct sysfs_addrm_cxt acxt; 38 int error; 39 40 sd = sysfs_new_dirent(name, S_IFLNK|S_IRWXUGO, SYSFS_KOBJ_LINK); 41 if (!sd) 42 return ERR_PTR(-ENOMEM); 43 44 if (parent->s_flags & SYSFS_FLAG_NS) 45 sd->s_ns = target->s_ns; 46 sd->s_symlink.target_sd = target; 47 kernfs_get(target); /* ref owned by symlink */ 48 49 sysfs_addrm_start(&acxt); 50 error = sysfs_add_one(&acxt, sd, parent); 51 sysfs_addrm_finish(&acxt); 52 53 if (!error) 54 return sd; 55 56 kernfs_put(sd); 57 return ERR_PTR(error); 58 } 59 60 61 static int sysfs_do_create_link_sd(struct sysfs_dirent *parent_sd, 62 struct kobject *target, 63 const char *name, int warn) 64 { 65 struct sysfs_dirent *sd, *target_sd = NULL; 66 67 BUG_ON(!name || !parent_sd); 68 69 /* 70 * We don't own @target and it may be removed at any time. 71 * Synchronize using sysfs_symlink_target_lock. See 72 * sysfs_remove_dir() for details. 73 */ 74 spin_lock(&sysfs_symlink_target_lock); 75 if (target->sd) { 76 target_sd = target->sd; 77 kernfs_get(target_sd); 78 } 79 spin_unlock(&sysfs_symlink_target_lock); 80 81 if (!target_sd) 82 return -ENOENT; 83 84 sd = kernfs_create_link(parent_sd, name, target_sd); 85 kernfs_put(target_sd); 86 87 if (!IS_ERR(sd)) 88 return 0; 89 90 if (warn && PTR_ERR(sd) == -EEXIST) 91 sysfs_warn_dup(parent_sd, name); 92 return PTR_ERR(sd); 93 } 94 95 /** 96 * sysfs_create_link_sd - create symlink to a given object. 97 * @sd: directory we're creating the link in. 98 * @target: object we're pointing to. 99 * @name: name of the symlink. 100 */ 101 int sysfs_create_link_sd(struct sysfs_dirent *sd, struct kobject *target, 102 const char *name) 103 { 104 return sysfs_do_create_link_sd(sd, target, name, 1); 105 } 106 107 static int sysfs_do_create_link(struct kobject *kobj, struct kobject *target, 108 const char *name, int warn) 109 { 110 struct sysfs_dirent *parent_sd = NULL; 111 112 if (!kobj) 113 parent_sd = &sysfs_root; 114 else 115 parent_sd = kobj->sd; 116 117 if (!parent_sd) 118 return -EFAULT; 119 120 return sysfs_do_create_link_sd(parent_sd, target, name, warn); 121 } 122 123 /** 124 * sysfs_create_link - create symlink between two objects. 125 * @kobj: object whose directory we're creating the link in. 126 * @target: object we're pointing to. 127 * @name: name of the symlink. 128 */ 129 int sysfs_create_link(struct kobject *kobj, struct kobject *target, 130 const char *name) 131 { 132 return sysfs_do_create_link(kobj, target, name, 1); 133 } 134 EXPORT_SYMBOL_GPL(sysfs_create_link); 135 136 /** 137 * sysfs_create_link_nowarn - create symlink between two objects. 138 * @kobj: object whose directory we're creating the link in. 139 * @target: object we're pointing to. 140 * @name: name of the symlink. 141 * 142 * This function does the same as sysfs_create_link(), but it 143 * doesn't warn if the link already exists. 144 */ 145 int sysfs_create_link_nowarn(struct kobject *kobj, struct kobject *target, 146 const char *name) 147 { 148 return sysfs_do_create_link(kobj, target, name, 0); 149 } 150 151 /** 152 * sysfs_delete_link - remove symlink in object's directory. 153 * @kobj: object we're acting for. 154 * @targ: object we're pointing to. 155 * @name: name of the symlink to remove. 156 * 157 * Unlike sysfs_remove_link sysfs_delete_link has enough information 158 * to successfully delete symlinks in tagged directories. 159 */ 160 void sysfs_delete_link(struct kobject *kobj, struct kobject *targ, 161 const char *name) 162 { 163 const void *ns = NULL; 164 165 /* 166 * We don't own @target and it may be removed at any time. 167 * Synchronize using sysfs_symlink_target_lock. See 168 * sysfs_remove_dir() for details. 169 */ 170 spin_lock(&sysfs_symlink_target_lock); 171 if (targ->sd && (kobj->sd->s_flags & SYSFS_FLAG_NS)) 172 ns = targ->sd->s_ns; 173 spin_unlock(&sysfs_symlink_target_lock); 174 kernfs_remove_by_name_ns(kobj->sd, name, ns); 175 } 176 177 /** 178 * sysfs_remove_link - remove symlink in object's directory. 179 * @kobj: object we're acting for. 180 * @name: name of the symlink to remove. 181 */ 182 void sysfs_remove_link(struct kobject *kobj, const char *name) 183 { 184 struct sysfs_dirent *parent_sd = NULL; 185 186 if (!kobj) 187 parent_sd = &sysfs_root; 188 else 189 parent_sd = kobj->sd; 190 191 kernfs_remove_by_name(parent_sd, name); 192 } 193 EXPORT_SYMBOL_GPL(sysfs_remove_link); 194 195 /** 196 * sysfs_rename_link_ns - rename symlink in object's directory. 197 * @kobj: object we're acting for. 198 * @targ: object we're pointing to. 199 * @old: previous name of the symlink. 200 * @new: new name of the symlink. 201 * @new_ns: new namespace of the symlink. 202 * 203 * A helper function for the common rename symlink idiom. 204 */ 205 int sysfs_rename_link_ns(struct kobject *kobj, struct kobject *targ, 206 const char *old, const char *new, const void *new_ns) 207 { 208 struct sysfs_dirent *parent_sd, *sd = NULL; 209 const void *old_ns = NULL; 210 int result; 211 212 if (!kobj) 213 parent_sd = &sysfs_root; 214 else 215 parent_sd = kobj->sd; 216 217 if (targ->sd) 218 old_ns = targ->sd->s_ns; 219 220 result = -ENOENT; 221 sd = kernfs_find_and_get_ns(parent_sd, old, old_ns); 222 if (!sd) 223 goto out; 224 225 result = -EINVAL; 226 if (sysfs_type(sd) != SYSFS_KOBJ_LINK) 227 goto out; 228 if (sd->s_symlink.target_sd->priv != targ) 229 goto out; 230 231 result = kernfs_rename_ns(sd, parent_sd, new, new_ns); 232 233 out: 234 kernfs_put(sd); 235 return result; 236 } 237 EXPORT_SYMBOL_GPL(sysfs_rename_link_ns); 238 239 static int sysfs_get_target_path(struct sysfs_dirent *parent_sd, 240 struct sysfs_dirent *target_sd, char *path) 241 { 242 struct sysfs_dirent *base, *sd; 243 char *s = path; 244 int len = 0; 245 246 /* go up to the root, stop at the base */ 247 base = parent_sd; 248 while (base->s_parent) { 249 sd = target_sd->s_parent; 250 while (sd->s_parent && base != sd) 251 sd = sd->s_parent; 252 253 if (base == sd) 254 break; 255 256 strcpy(s, "../"); 257 s += 3; 258 base = base->s_parent; 259 } 260 261 /* determine end of target string for reverse fillup */ 262 sd = target_sd; 263 while (sd->s_parent && sd != base) { 264 len += strlen(sd->s_name) + 1; 265 sd = sd->s_parent; 266 } 267 268 /* check limits */ 269 if (len < 2) 270 return -EINVAL; 271 len--; 272 if ((s - path) + len > PATH_MAX) 273 return -ENAMETOOLONG; 274 275 /* reverse fillup of target string from target to base */ 276 sd = target_sd; 277 while (sd->s_parent && sd != base) { 278 int slen = strlen(sd->s_name); 279 280 len -= slen; 281 strncpy(s + len, sd->s_name, slen); 282 if (len) 283 s[--len] = '/'; 284 285 sd = sd->s_parent; 286 } 287 288 return 0; 289 } 290 291 static int sysfs_getlink(struct dentry *dentry, char *path) 292 { 293 struct sysfs_dirent *sd = dentry->d_fsdata; 294 struct sysfs_dirent *parent_sd = sd->s_parent; 295 struct sysfs_dirent *target_sd = sd->s_symlink.target_sd; 296 int error; 297 298 mutex_lock(&sysfs_mutex); 299 error = sysfs_get_target_path(parent_sd, target_sd, path); 300 mutex_unlock(&sysfs_mutex); 301 302 return error; 303 } 304 305 static void *sysfs_follow_link(struct dentry *dentry, struct nameidata *nd) 306 { 307 int error = -ENOMEM; 308 unsigned long page = get_zeroed_page(GFP_KERNEL); 309 if (page) { 310 error = sysfs_getlink(dentry, (char *) page); 311 if (error < 0) 312 free_page((unsigned long)page); 313 } 314 nd_set_link(nd, error ? ERR_PTR(error) : (char *)page); 315 return NULL; 316 } 317 318 static void sysfs_put_link(struct dentry *dentry, struct nameidata *nd, 319 void *cookie) 320 { 321 char *page = nd_get_link(nd); 322 if (!IS_ERR(page)) 323 free_page((unsigned long)page); 324 } 325 326 const struct inode_operations sysfs_symlink_inode_operations = { 327 .setxattr = sysfs_setxattr, 328 .readlink = generic_readlink, 329 .follow_link = sysfs_follow_link, 330 .put_link = sysfs_put_link, 331 .setattr = sysfs_setattr, 332 .getattr = sysfs_getattr, 333 .permission = sysfs_permission, 334 }; 335