symlink.c 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308
  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. #include <linux/fs.h>
  13. #include <linux/gfp.h>
  14. #include <linux/mount.h>
  15. #include <linux/module.h>
  16. #include <linux/kobject.h>
  17. #include <linux/namei.h>
  18. #include <linux/mutex.h>
  19. #include <linux/security.h>
  20. #include "sysfs.h"
  21. static int sysfs_do_create_link(struct kobject *kobj, struct kobject *target,
  22. const char *name, int warn)
  23. {
  24. struct sysfs_dirent *parent_sd = NULL;
  25. struct sysfs_dirent *target_sd = NULL;
  26. struct sysfs_dirent *sd = NULL;
  27. struct sysfs_addrm_cxt acxt;
  28. enum kobj_ns_type ns_type;
  29. int error;
  30. BUG_ON(!name);
  31. if (!kobj)
  32. parent_sd = &sysfs_root;
  33. else
  34. parent_sd = kobj->sd;
  35. error = -EFAULT;
  36. if (!parent_sd)
  37. goto out_put;
  38. /* target->sd can go away beneath us but is protected with
  39. * sysfs_assoc_lock. Fetch target_sd from it.
  40. */
  41. spin_lock(&sysfs_assoc_lock);
  42. if (target->sd)
  43. target_sd = sysfs_get(target->sd);
  44. spin_unlock(&sysfs_assoc_lock);
  45. error = -ENOENT;
  46. if (!target_sd)
  47. goto out_put;
  48. error = -ENOMEM;
  49. sd = sysfs_new_dirent(name, S_IFLNK|S_IRWXUGO, SYSFS_KOBJ_LINK);
  50. if (!sd)
  51. goto out_put;
  52. ns_type = sysfs_ns_type(parent_sd);
  53. if (ns_type)
  54. sd->s_ns = target->ktype->namespace(target);
  55. sd->s_symlink.target_sd = target_sd;
  56. target_sd = NULL; /* reference is now owned by the symlink */
  57. sysfs_addrm_start(&acxt, parent_sd);
  58. /* Symlinks must be between directories with the same ns_type */
  59. if (!ns_type ||
  60. (ns_type == sysfs_ns_type(sd->s_symlink.target_sd->s_parent))) {
  61. if (warn)
  62. error = sysfs_add_one(&acxt, sd);
  63. else
  64. error = __sysfs_add_one(&acxt, sd);
  65. } else {
  66. error = -EINVAL;
  67. WARN(1, KERN_WARNING
  68. "sysfs: symlink across ns_types %s/%s -> %s/%s\n",
  69. parent_sd->s_name,
  70. sd->s_name,
  71. sd->s_symlink.target_sd->s_parent->s_name,
  72. sd->s_symlink.target_sd->s_name);
  73. }
  74. sysfs_addrm_finish(&acxt);
  75. if (error)
  76. goto out_put;
  77. return 0;
  78. out_put:
  79. sysfs_put(target_sd);
  80. sysfs_put(sd);
  81. return error;
  82. }
  83. /**
  84. * sysfs_create_link - create symlink between two objects.
  85. * @kobj: object whose directory we're creating the link in.
  86. * @target: object we're pointing to.
  87. * @name: name of the symlink.
  88. */
  89. int sysfs_create_link(struct kobject *kobj, struct kobject *target,
  90. const char *name)
  91. {
  92. return sysfs_do_create_link(kobj, target, name, 1);
  93. }
  94. /**
  95. * sysfs_create_link_nowarn - create symlink between two objects.
  96. * @kobj: object whose directory we're creating the link in.
  97. * @target: object we're pointing to.
  98. * @name: name of the symlink.
  99. *
  100. * This function does the same as sysf_create_link(), but it
  101. * doesn't warn if the link already exists.
  102. */
  103. int sysfs_create_link_nowarn(struct kobject *kobj, struct kobject *target,
  104. const char *name)
  105. {
  106. return sysfs_do_create_link(kobj, target, name, 0);
  107. }
  108. /**
  109. * sysfs_delete_link - remove symlink in object's directory.
  110. * @kobj: object we're acting for.
  111. * @targ: object we're pointing to.
  112. * @name: name of the symlink to remove.
  113. *
  114. * Unlike sysfs_remove_link sysfs_delete_link has enough information
  115. * to successfully delete symlinks in tagged directories.
  116. */
  117. void sysfs_delete_link(struct kobject *kobj, struct kobject *targ,
  118. const char *name)
  119. {
  120. const void *ns = NULL;
  121. spin_lock(&sysfs_assoc_lock);
  122. if (targ->sd && sysfs_ns_type(kobj->sd))
  123. ns = targ->sd->s_ns;
  124. spin_unlock(&sysfs_assoc_lock);
  125. sysfs_hash_and_remove(kobj->sd, ns, name);
  126. }
  127. /**
  128. * sysfs_remove_link - remove symlink in object's directory.
  129. * @kobj: object we're acting for.
  130. * @name: name of the symlink to remove.
  131. */
  132. void sysfs_remove_link(struct kobject * kobj, const char * name)
  133. {
  134. struct sysfs_dirent *parent_sd = NULL;
  135. if (!kobj)
  136. parent_sd = &sysfs_root;
  137. else
  138. parent_sd = kobj->sd;
  139. sysfs_hash_and_remove(parent_sd, NULL, name);
  140. }
  141. /**
  142. * sysfs_rename_link - rename symlink in object's directory.
  143. * @kobj: object we're acting for.
  144. * @targ: object we're pointing to.
  145. * @old: previous name of the symlink.
  146. * @new: new name of the symlink.
  147. *
  148. * A helper function for the common rename symlink idiom.
  149. */
  150. int sysfs_rename_link(struct kobject *kobj, struct kobject *targ,
  151. const char *old, const char *new)
  152. {
  153. struct sysfs_dirent *parent_sd, *sd = NULL;
  154. const void *old_ns = NULL, *new_ns = NULL;
  155. int result;
  156. if (!kobj)
  157. parent_sd = &sysfs_root;
  158. else
  159. parent_sd = kobj->sd;
  160. if (targ->sd)
  161. old_ns = targ->sd->s_ns;
  162. result = -ENOENT;
  163. sd = sysfs_get_dirent(parent_sd, old_ns, old);
  164. if (!sd)
  165. goto out;
  166. result = -EINVAL;
  167. if (sysfs_type(sd) != SYSFS_KOBJ_LINK)
  168. goto out;
  169. if (sd->s_symlink.target_sd->s_dir.kobj != targ)
  170. goto out;
  171. if (sysfs_ns_type(parent_sd))
  172. new_ns = targ->ktype->namespace(targ);
  173. result = sysfs_rename(sd, parent_sd, new_ns, new);
  174. out:
  175. sysfs_put(sd);
  176. return result;
  177. }
  178. static int sysfs_get_target_path(struct sysfs_dirent *parent_sd,
  179. struct sysfs_dirent *target_sd, char *path)
  180. {
  181. struct sysfs_dirent *base, *sd;
  182. char *s = path;
  183. int len = 0;
  184. /* go up to the root, stop at the base */
  185. base = parent_sd;
  186. while (base->s_parent) {
  187. sd = target_sd->s_parent;
  188. while (sd->s_parent && base != sd)
  189. sd = sd->s_parent;
  190. if (base == sd)
  191. break;
  192. strcpy(s, "../");
  193. s += 3;
  194. base = base->s_parent;
  195. }
  196. /* determine end of target string for reverse fillup */
  197. sd = target_sd;
  198. while (sd->s_parent && sd != base) {
  199. len += strlen(sd->s_name) + 1;
  200. sd = sd->s_parent;
  201. }
  202. /* check limits */
  203. if (len < 2)
  204. return -EINVAL;
  205. len--;
  206. if ((s - path) + len > PATH_MAX)
  207. return -ENAMETOOLONG;
  208. /* reverse fillup of target string from target to base */
  209. sd = target_sd;
  210. while (sd->s_parent && sd != base) {
  211. int slen = strlen(sd->s_name);
  212. len -= slen;
  213. strncpy(s + len, sd->s_name, slen);
  214. if (len)
  215. s[--len] = '/';
  216. sd = sd->s_parent;
  217. }
  218. return 0;
  219. }
  220. static int sysfs_getlink(struct dentry *dentry, char * path)
  221. {
  222. struct sysfs_dirent *sd = dentry->d_fsdata;
  223. struct sysfs_dirent *parent_sd = sd->s_parent;
  224. struct sysfs_dirent *target_sd = sd->s_symlink.target_sd;
  225. int error;
  226. mutex_lock(&sysfs_mutex);
  227. error = sysfs_get_target_path(parent_sd, target_sd, path);
  228. mutex_unlock(&sysfs_mutex);
  229. return error;
  230. }
  231. static void *sysfs_follow_link(struct dentry *dentry, struct nameidata *nd)
  232. {
  233. int error = -ENOMEM;
  234. unsigned long page = get_zeroed_page(GFP_KERNEL);
  235. if (page) {
  236. error = sysfs_getlink(dentry, (char *) page);
  237. if (error < 0)
  238. free_page((unsigned long)page);
  239. }
  240. nd_set_link(nd, error ? ERR_PTR(error) : (char *)page);
  241. return NULL;
  242. }
  243. static void sysfs_put_link(struct dentry *dentry, struct nameidata *nd, void *cookie)
  244. {
  245. char *page = nd_get_link(nd);
  246. if (!IS_ERR(page))
  247. free_page((unsigned long)page);
  248. }
  249. const struct inode_operations sysfs_symlink_inode_operations = {
  250. .setxattr = sysfs_setxattr,
  251. .readlink = generic_readlink,
  252. .follow_link = sysfs_follow_link,
  253. .put_link = sysfs_put_link,
  254. .setattr = sysfs_setattr,
  255. .getattr = sysfs_getattr,
  256. .permission = sysfs_permission,
  257. };
  258. EXPORT_SYMBOL_GPL(sysfs_create_link);
  259. EXPORT_SYMBOL_GPL(sysfs_remove_link);
  260. EXPORT_SYMBOL_GPL(sysfs_rename_link);