^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * fs/kernfs/symlink.c - kernfs symlink implementation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (c) 2001-3 Patrick Mochel
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Copyright (c) 2007 SUSE Linux Products GmbH
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Copyright (c) 2007, 2013 Tejun Heo <tj@kernel.org>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/fs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/gfp.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/namei.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include "kernfs-internal.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) * kernfs_create_link - create a symlink
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) * @parent: directory to create the symlink in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) * @name: name of the symlink
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) * @target: target node for the symlink to point to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) * Returns the created node on success, ERR_PTR() value on error.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) * Ownership of the link matches ownership of the target.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) struct kernfs_node *kernfs_create_link(struct kernfs_node *parent,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) const char *name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) struct kernfs_node *target)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) struct kernfs_node *kn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) int error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) kuid_t uid = GLOBAL_ROOT_UID;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) kgid_t gid = GLOBAL_ROOT_GID;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) if (target->iattr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) uid = target->iattr->ia_uid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) gid = target->iattr->ia_gid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) kn = kernfs_new_node(parent, name, S_IFLNK|S_IRWXUGO, uid, gid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) KERNFS_LINK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) if (!kn)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) return ERR_PTR(-ENOMEM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) if (kernfs_ns_enabled(parent))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) kn->ns = target->ns;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) kn->symlink.target_kn = target;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) kernfs_get(target); /* ref owned by symlink */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) error = kernfs_add_one(kn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) if (!error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) return kn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) kernfs_put(kn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) return ERR_PTR(error);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) static int kernfs_get_target_path(struct kernfs_node *parent,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) struct kernfs_node *target, char *path)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) struct kernfs_node *base, *kn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) char *s = path;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) int len = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) /* go up to the root, stop at the base */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) base = parent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) while (base->parent) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) kn = target->parent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) while (kn->parent && base != kn)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) kn = kn->parent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) if (base == kn)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) if ((s - path) + 3 >= PATH_MAX)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) return -ENAMETOOLONG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) strcpy(s, "../");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) s += 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) base = base->parent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) /* determine end of target string for reverse fillup */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) kn = target;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) while (kn->parent && kn != base) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) len += strlen(kn->name) + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) kn = kn->parent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) /* check limits */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) if (len < 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) len--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) if ((s - path) + len >= PATH_MAX)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) return -ENAMETOOLONG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) /* reverse fillup of target string from target to base */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) kn = target;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) while (kn->parent && kn != base) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) int slen = strlen(kn->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) len -= slen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) memcpy(s + len, kn->name, slen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) if (len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) s[--len] = '/';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) kn = kn->parent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) static int kernfs_getlink(struct inode *inode, char *path)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) struct kernfs_node *kn = inode->i_private;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) struct kernfs_node *parent = kn->parent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) struct kernfs_node *target = kn->symlink.target_kn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) int error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) mutex_lock(&kernfs_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) error = kernfs_get_target_path(parent, target, path);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) mutex_unlock(&kernfs_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) static const char *kernfs_iop_get_link(struct dentry *dentry,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) struct inode *inode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) struct delayed_call *done)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) char *body;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) int error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) if (!dentry)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) return ERR_PTR(-ECHILD);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) body = kzalloc(PAGE_SIZE, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) if (!body)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) return ERR_PTR(-ENOMEM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) error = kernfs_getlink(inode, body);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) if (unlikely(error < 0)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) kfree(body);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) return ERR_PTR(error);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) set_delayed_call(done, kfree_link, body);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) return body;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) const struct inode_operations kernfs_symlink_iops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) .listxattr = kernfs_iop_listxattr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) .get_link = kernfs_iop_get_link,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) .setattr = kernfs_iop_setattr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) .getattr = kernfs_iop_getattr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) .permission = kernfs_iop_permission,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) };