summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDmitry Torokhov <dmitry.torokhov@gmail.com>2018-07-20 17:56:47 -0400
committerDavid S. Miller <davem@davemloft.net>2018-07-21 02:44:35 -0400
commit488dee96bb62f0b3d9e678cf42574034d5b033a5 (patch)
tree2969d47ffb0ffeaf15d20ffb0eda78a2bb694a40
parent7c4ec749a3bd89237d7195ccd621bf5d4124d6b5 (diff)
kernfs: allow creating kernfs objects with arbitrary uid/gid
This change allows creating kernfs files and directories with arbitrary uid/gid instead of always using GLOBAL_ROOT_UID/GID by extending kernfs_create_dir_ns() and kernfs_create_file_ns() with uid/gid arguments. The "simple" kernfs_create_file() and kernfs_create_dir() are left alone and always create objects belonging to the global root. When creating symlinks ownership (uid/gid) is taken from the target kernfs object. Co-Developed-by: Tyler Hicks <tyhicks@canonical.com> Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com> Signed-off-by: Tyler Hicks <tyhicks@canonical.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--arch/x86/kernel/cpu/intel_rdt_rdtgroup.c4
-rw-r--r--fs/kernfs/dir.c29
-rw-r--r--fs/kernfs/file.c8
-rw-r--r--fs/kernfs/inode.c2
-rw-r--r--fs/kernfs/kernfs-internal.h2
-rw-r--r--fs/kernfs/symlink.c11
-rw-r--r--fs/sysfs/dir.c4
-rw-r--r--fs/sysfs/file.c5
-rw-r--r--include/linux/kernfs.h28
-rw-r--r--kernel/cgroup/cgroup.c4
10 files changed, 76 insertions, 21 deletions
diff --git a/arch/x86/kernel/cpu/intel_rdt_rdtgroup.c b/arch/x86/kernel/cpu/intel_rdt_rdtgroup.c
index 749856a2e736..9af1a21265d3 100644
--- a/arch/x86/kernel/cpu/intel_rdt_rdtgroup.c
+++ b/arch/x86/kernel/cpu/intel_rdt_rdtgroup.c
@@ -146,6 +146,7 @@ static int rdtgroup_add_file(struct kernfs_node *parent_kn, struct rftype *rft)
146 int ret; 146 int ret;
147 147
148 kn = __kernfs_create_file(parent_kn, rft->name, rft->mode, 148 kn = __kernfs_create_file(parent_kn, rft->name, rft->mode,
149 GLOBAL_ROOT_UID, GLOBAL_ROOT_GID,
149 0, rft->kf_ops, rft, NULL, NULL); 150 0, rft->kf_ops, rft, NULL, NULL);
150 if (IS_ERR(kn)) 151 if (IS_ERR(kn))
151 return PTR_ERR(kn); 152 return PTR_ERR(kn);
@@ -1503,7 +1504,8 @@ static int mon_addfile(struct kernfs_node *parent_kn, const char *name,
1503 struct kernfs_node *kn; 1504 struct kernfs_node *kn;
1504 int ret = 0; 1505 int ret = 0;
1505 1506
1506 kn = __kernfs_create_file(parent_kn, name, 0444, 0, 1507 kn = __kernfs_create_file(parent_kn, name, 0444,
1508 GLOBAL_ROOT_UID, GLOBAL_ROOT_GID, 0,
1507 &kf_mondata_ops, priv, NULL, NULL); 1509 &kf_mondata_ops, priv, NULL, NULL);
1508 if (IS_ERR(kn)) 1510 if (IS_ERR(kn))
1509 return PTR_ERR(kn); 1511 return PTR_ERR(kn);
diff --git a/fs/kernfs/dir.c b/fs/kernfs/dir.c
index d66cc0777303..4ca0b5c18192 100644
--- a/fs/kernfs/dir.c
+++ b/fs/kernfs/dir.c
@@ -619,6 +619,7 @@ struct kernfs_node *kernfs_node_from_dentry(struct dentry *dentry)
619 619
620static struct kernfs_node *__kernfs_new_node(struct kernfs_root *root, 620static struct kernfs_node *__kernfs_new_node(struct kernfs_root *root,
621 const char *name, umode_t mode, 621 const char *name, umode_t mode,
622 kuid_t uid, kgid_t gid,
622 unsigned flags) 623 unsigned flags)
623{ 624{
624 struct kernfs_node *kn; 625 struct kernfs_node *kn;
@@ -661,8 +662,22 @@ static struct kernfs_node *__kernfs_new_node(struct kernfs_root *root,
661 kn->mode = mode; 662 kn->mode = mode;
662 kn->flags = flags; 663 kn->flags = flags;
663 664
665 if (!uid_eq(uid, GLOBAL_ROOT_UID) || !gid_eq(gid, GLOBAL_ROOT_GID)) {
666 struct iattr iattr = {
667 .ia_valid = ATTR_UID | ATTR_GID,
668 .ia_uid = uid,
669 .ia_gid = gid,
670 };
671
672 ret = __kernfs_setattr(kn, &iattr);
673 if (ret < 0)
674 goto err_out3;
675 }
676
664 return kn; 677 return kn;
665 678
679 err_out3:
680 idr_remove(&root->ino_idr, kn->id.ino);
666 err_out2: 681 err_out2:
667 kmem_cache_free(kernfs_node_cache, kn); 682 kmem_cache_free(kernfs_node_cache, kn);
668 err_out1: 683 err_out1:
@@ -672,11 +687,13 @@ static struct kernfs_node *__kernfs_new_node(struct kernfs_root *root,
672 687
673struct kernfs_node *kernfs_new_node(struct kernfs_node *parent, 688struct kernfs_node *kernfs_new_node(struct kernfs_node *parent,
674 const char *name, umode_t mode, 689 const char *name, umode_t mode,
690 kuid_t uid, kgid_t gid,
675 unsigned flags) 691 unsigned flags)
676{ 692{
677 struct kernfs_node *kn; 693 struct kernfs_node *kn;
678 694
679 kn = __kernfs_new_node(kernfs_root(parent), name, mode, flags); 695 kn = __kernfs_new_node(kernfs_root(parent),
696 name, mode, uid, gid, flags);
680 if (kn) { 697 if (kn) {
681 kernfs_get(parent); 698 kernfs_get(parent);
682 kn->parent = parent; 699 kn->parent = parent;
@@ -946,6 +963,7 @@ struct kernfs_root *kernfs_create_root(struct kernfs_syscall_ops *scops,
946 root->next_generation = 1; 963 root->next_generation = 1;
947 964
948 kn = __kernfs_new_node(root, "", S_IFDIR | S_IRUGO | S_IXUGO, 965 kn = __kernfs_new_node(root, "", S_IFDIR | S_IRUGO | S_IXUGO,
966 GLOBAL_ROOT_UID, GLOBAL_ROOT_GID,
949 KERNFS_DIR); 967 KERNFS_DIR);
950 if (!kn) { 968 if (!kn) {
951 idr_destroy(&root->ino_idr); 969 idr_destroy(&root->ino_idr);
@@ -984,6 +1002,8 @@ void kernfs_destroy_root(struct kernfs_root *root)
984 * @parent: parent in which to create a new directory 1002 * @parent: parent in which to create a new directory
985 * @name: name of the new directory 1003 * @name: name of the new directory
986 * @mode: mode of the new directory 1004 * @mode: mode of the new directory
1005 * @uid: uid of the new directory
1006 * @gid: gid of the new directory
987 * @priv: opaque data associated with the new directory 1007 * @priv: opaque data associated with the new directory
988 * @ns: optional namespace tag of the directory 1008 * @ns: optional namespace tag of the directory
989 * 1009 *
@@ -991,13 +1011,15 @@ void kernfs_destroy_root(struct kernfs_root *root)
991 */ 1011 */
992struct kernfs_node *kernfs_create_dir_ns(struct kernfs_node *parent, 1012struct kernfs_node *kernfs_create_dir_ns(struct kernfs_node *parent,
993 const char *name, umode_t mode, 1013 const char *name, umode_t mode,
1014 kuid_t uid, kgid_t gid,
994 void *priv, const void *ns) 1015 void *priv, const void *ns)
995{ 1016{
996 struct kernfs_node *kn; 1017 struct kernfs_node *kn;
997 int rc; 1018 int rc;
998 1019
999 /* allocate */ 1020 /* allocate */
1000 kn = kernfs_new_node(parent, name, mode | S_IFDIR, KERNFS_DIR); 1021 kn = kernfs_new_node(parent, name, mode | S_IFDIR,
1022 uid, gid, KERNFS_DIR);
1001 if (!kn) 1023 if (!kn)
1002 return ERR_PTR(-ENOMEM); 1024 return ERR_PTR(-ENOMEM);
1003 1025
@@ -1028,7 +1050,8 @@ struct kernfs_node *kernfs_create_empty_dir(struct kernfs_node *parent,
1028 int rc; 1050 int rc;
1029 1051
1030 /* allocate */ 1052 /* allocate */
1031 kn = kernfs_new_node(parent, name, S_IRUGO|S_IXUGO|S_IFDIR, KERNFS_DIR); 1053 kn = kernfs_new_node(parent, name, S_IRUGO|S_IXUGO|S_IFDIR,
1054 GLOBAL_ROOT_UID, GLOBAL_ROOT_GID, KERNFS_DIR);
1032 if (!kn) 1055 if (!kn)
1033 return ERR_PTR(-ENOMEM); 1056 return ERR_PTR(-ENOMEM);
1034 1057
diff --git a/fs/kernfs/file.c b/fs/kernfs/file.c
index 2015d8c45e4a..dbf5bc250bfd 100644
--- a/fs/kernfs/file.c
+++ b/fs/kernfs/file.c
@@ -965,6 +965,8 @@ const struct file_operations kernfs_file_fops = {
965 * @parent: directory to create the file in 965 * @parent: directory to create the file in
966 * @name: name of the file 966 * @name: name of the file
967 * @mode: mode of the file 967 * @mode: mode of the file
968 * @uid: uid of the file
969 * @gid: gid of the file
968 * @size: size of the file 970 * @size: size of the file
969 * @ops: kernfs operations for the file 971 * @ops: kernfs operations for the file
970 * @priv: private data for the file 972 * @priv: private data for the file
@@ -975,7 +977,8 @@ const struct file_operations kernfs_file_fops = {
975 */ 977 */
976struct kernfs_node *__kernfs_create_file(struct kernfs_node *parent, 978struct kernfs_node *__kernfs_create_file(struct kernfs_node *parent,
977 const char *name, 979 const char *name,
978 umode_t mode, loff_t size, 980 umode_t mode, kuid_t uid, kgid_t gid,
981 loff_t size,
979 const struct kernfs_ops *ops, 982 const struct kernfs_ops *ops,
980 void *priv, const void *ns, 983 void *priv, const void *ns,
981 struct lock_class_key *key) 984 struct lock_class_key *key)
@@ -986,7 +989,8 @@ struct kernfs_node *__kernfs_create_file(struct kernfs_node *parent,
986 989
987 flags = KERNFS_FILE; 990 flags = KERNFS_FILE;
988 991
989 kn = kernfs_new_node(parent, name, (mode & S_IALLUGO) | S_IFREG, flags); 992 kn = kernfs_new_node(parent, name, (mode & S_IALLUGO) | S_IFREG,
993 uid, gid, flags);
990 if (!kn) 994 if (!kn)
991 return ERR_PTR(-ENOMEM); 995 return ERR_PTR(-ENOMEM);
992 996
diff --git a/fs/kernfs/inode.c b/fs/kernfs/inode.c
index 3d73fe9d56e2..80cebcd94c90 100644
--- a/fs/kernfs/inode.c
+++ b/fs/kernfs/inode.c
@@ -63,7 +63,7 @@ out_unlock:
63 return ret; 63 return ret;
64} 64}
65 65
66static int __kernfs_setattr(struct kernfs_node *kn, const struct iattr *iattr) 66int __kernfs_setattr(struct kernfs_node *kn, const struct iattr *iattr)
67{ 67{
68 struct kernfs_iattrs *attrs; 68 struct kernfs_iattrs *attrs;
69 struct iattr *iattrs; 69 struct iattr *iattrs;
diff --git a/fs/kernfs/kernfs-internal.h b/fs/kernfs/kernfs-internal.h
index 0f260dcca177..3d83b114bb08 100644
--- a/fs/kernfs/kernfs-internal.h
+++ b/fs/kernfs/kernfs-internal.h
@@ -90,6 +90,7 @@ int kernfs_iop_setattr(struct dentry *dentry, struct iattr *iattr);
90int kernfs_iop_getattr(const struct path *path, struct kstat *stat, 90int kernfs_iop_getattr(const struct path *path, struct kstat *stat,
91 u32 request_mask, unsigned int query_flags); 91 u32 request_mask, unsigned int query_flags);
92ssize_t kernfs_iop_listxattr(struct dentry *dentry, char *buf, size_t size); 92ssize_t kernfs_iop_listxattr(struct dentry *dentry, char *buf, size_t size);
93int __kernfs_setattr(struct kernfs_node *kn, const struct iattr *iattr);
93 94
94/* 95/*
95 * dir.c 96 * dir.c
@@ -104,6 +105,7 @@ void kernfs_put_active(struct kernfs_node *kn);
104int kernfs_add_one(struct kernfs_node *kn); 105int kernfs_add_one(struct kernfs_node *kn);
105struct kernfs_node *kernfs_new_node(struct kernfs_node *parent, 106struct kernfs_node *kernfs_new_node(struct kernfs_node *parent,
106 const char *name, umode_t mode, 107 const char *name, umode_t mode,
108 kuid_t uid, kgid_t gid,
107 unsigned flags); 109 unsigned flags);
108struct kernfs_node *kernfs_find_and_get_node_by_ino(struct kernfs_root *root, 110struct kernfs_node *kernfs_find_and_get_node_by_ino(struct kernfs_root *root,
109 unsigned int ino); 111 unsigned int ino);
diff --git a/fs/kernfs/symlink.c b/fs/kernfs/symlink.c
index 08ccabd7047f..5ffed48f3d0e 100644
--- a/fs/kernfs/symlink.c
+++ b/fs/kernfs/symlink.c
@@ -21,6 +21,7 @@
21 * @target: target node for the symlink to point to 21 * @target: target node for the symlink to point to
22 * 22 *
23 * Returns the created node on success, ERR_PTR() value on error. 23 * Returns the created node on success, ERR_PTR() value on error.
24 * Ownership of the link matches ownership of the target.
24 */ 25 */
25struct kernfs_node *kernfs_create_link(struct kernfs_node *parent, 26struct kernfs_node *kernfs_create_link(struct kernfs_node *parent,
26 const char *name, 27 const char *name,
@@ -28,8 +29,16 @@ struct kernfs_node *kernfs_create_link(struct kernfs_node *parent,
28{ 29{
29 struct kernfs_node *kn; 30 struct kernfs_node *kn;
30 int error; 31 int error;
32 kuid_t uid = GLOBAL_ROOT_UID;
33 kgid_t gid = GLOBAL_ROOT_GID;
31 34
32 kn = kernfs_new_node(parent, name, S_IFLNK|S_IRWXUGO, KERNFS_LINK); 35 if (target->iattr) {
36 uid = target->iattr->ia_iattr.ia_uid;
37 gid = target->iattr->ia_iattr.ia_gid;
38 }
39
40 kn = kernfs_new_node(parent, name, S_IFLNK|S_IRWXUGO, uid, gid,
41 KERNFS_LINK);
33 if (!kn) 42 if (!kn)
34 return ERR_PTR(-ENOMEM); 43 return ERR_PTR(-ENOMEM);
35 44
diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c
index 58eba92a0e41..e39b884f0867 100644
--- a/fs/sysfs/dir.c
+++ b/fs/sysfs/dir.c
@@ -52,7 +52,9 @@ int sysfs_create_dir_ns(struct kobject *kobj, const void *ns)
52 return -ENOENT; 52 return -ENOENT;
53 53
54 kn = kernfs_create_dir_ns(parent, kobject_name(kobj), 54 kn = kernfs_create_dir_ns(parent, kobject_name(kobj),
55 S_IRWXU | S_IRUGO | S_IXUGO, kobj, ns); 55 S_IRWXU | S_IRUGO | S_IXUGO,
56 GLOBAL_ROOT_UID, GLOBAL_ROOT_GID,
57 kobj, ns);
56 if (IS_ERR(kn)) { 58 if (IS_ERR(kn)) {
57 if (PTR_ERR(kn) == -EEXIST) 59 if (PTR_ERR(kn) == -EEXIST)
58 sysfs_warn_dup(parent, kobject_name(kobj)); 60 sysfs_warn_dup(parent, kobject_name(kobj));
diff --git a/fs/sysfs/file.c b/fs/sysfs/file.c
index 5c13f29bfcdb..513fa691ecbd 100644
--- a/fs/sysfs/file.c
+++ b/fs/sysfs/file.c
@@ -302,8 +302,9 @@ int sysfs_add_file_mode_ns(struct kernfs_node *parent,
302 if (!attr->ignore_lockdep) 302 if (!attr->ignore_lockdep)
303 key = attr->key ?: (struct lock_class_key *)&attr->skey; 303 key = attr->key ?: (struct lock_class_key *)&attr->skey;
304#endif 304#endif
305 kn = __kernfs_create_file(parent, attr->name, mode & 0777, size, ops, 305 kn = __kernfs_create_file(parent, attr->name,
306 (void *)attr, ns, key); 306 mode & 0777, GLOBAL_ROOT_UID, GLOBAL_ROOT_GID,
307 size, ops, (void *)attr, ns, key);
307 if (IS_ERR(kn)) { 308 if (IS_ERR(kn)) {
308 if (PTR_ERR(kn) == -EEXIST) 309 if (PTR_ERR(kn) == -EEXIST)
309 sysfs_warn_dup(parent, attr->name); 310 sysfs_warn_dup(parent, attr->name);
diff --git a/include/linux/kernfs.h b/include/linux/kernfs.h
index ab25c8b6d9e3..814643f7ee52 100644
--- a/include/linux/kernfs.h
+++ b/include/linux/kernfs.h
@@ -15,6 +15,7 @@
15#include <linux/lockdep.h> 15#include <linux/lockdep.h>
16#include <linux/rbtree.h> 16#include <linux/rbtree.h>
17#include <linux/atomic.h> 17#include <linux/atomic.h>
18#include <linux/uidgid.h>
18#include <linux/wait.h> 19#include <linux/wait.h>
19 20
20struct file; 21struct file;
@@ -325,12 +326,14 @@ void kernfs_destroy_root(struct kernfs_root *root);
325 326
326struct kernfs_node *kernfs_create_dir_ns(struct kernfs_node *parent, 327struct kernfs_node *kernfs_create_dir_ns(struct kernfs_node *parent,
327 const char *name, umode_t mode, 328 const char *name, umode_t mode,
329 kuid_t uid, kgid_t gid,
328 void *priv, const void *ns); 330 void *priv, const void *ns);
329struct kernfs_node *kernfs_create_empty_dir(struct kernfs_node *parent, 331struct kernfs_node *kernfs_create_empty_dir(struct kernfs_node *parent,
330 const char *name); 332 const char *name);
331struct kernfs_node *__kernfs_create_file(struct kernfs_node *parent, 333struct kernfs_node *__kernfs_create_file(struct kernfs_node *parent,
332 const char *name, 334 const char *name, umode_t mode,
333 umode_t mode, loff_t size, 335 kuid_t uid, kgid_t gid,
336 loff_t size,
334 const struct kernfs_ops *ops, 337 const struct kernfs_ops *ops,
335 void *priv, const void *ns, 338 void *priv, const void *ns,
336 struct lock_class_key *key); 339 struct lock_class_key *key);
@@ -415,12 +418,14 @@ static inline void kernfs_destroy_root(struct kernfs_root *root) { }
415 418
416static inline struct kernfs_node * 419static inline struct kernfs_node *
417kernfs_create_dir_ns(struct kernfs_node *parent, const char *name, 420kernfs_create_dir_ns(struct kernfs_node *parent, const char *name,
418 umode_t mode, void *priv, const void *ns) 421 umode_t mode, kuid_t uid, kgid_t gid,
422 void *priv, const void *ns)
419{ return ERR_PTR(-ENOSYS); } 423{ return ERR_PTR(-ENOSYS); }
420 424
421static inline struct kernfs_node * 425static inline struct kernfs_node *
422__kernfs_create_file(struct kernfs_node *parent, const char *name, 426__kernfs_create_file(struct kernfs_node *parent, const char *name,
423 umode_t mode, loff_t size, const struct kernfs_ops *ops, 427 umode_t mode, kuid_t uid, kgid_t gid,
428 loff_t size, const struct kernfs_ops *ops,
424 void *priv, const void *ns, struct lock_class_key *key) 429 void *priv, const void *ns, struct lock_class_key *key)
425{ return ERR_PTR(-ENOSYS); } 430{ return ERR_PTR(-ENOSYS); }
426 431
@@ -498,12 +503,15 @@ static inline struct kernfs_node *
498kernfs_create_dir(struct kernfs_node *parent, const char *name, umode_t mode, 503kernfs_create_dir(struct kernfs_node *parent, const char *name, umode_t mode,
499 void *priv) 504 void *priv)
500{ 505{
501 return kernfs_create_dir_ns(parent, name, mode, priv, NULL); 506 return kernfs_create_dir_ns(parent, name, mode,
507 GLOBAL_ROOT_UID, GLOBAL_ROOT_GID,
508 priv, NULL);
502} 509}
503 510
504static inline struct kernfs_node * 511static inline struct kernfs_node *
505kernfs_create_file_ns(struct kernfs_node *parent, const char *name, 512kernfs_create_file_ns(struct kernfs_node *parent, const char *name,
506 umode_t mode, loff_t size, const struct kernfs_ops *ops, 513 umode_t mode, kuid_t uid, kgid_t gid,
514 loff_t size, const struct kernfs_ops *ops,
507 void *priv, const void *ns) 515 void *priv, const void *ns)
508{ 516{
509 struct lock_class_key *key = NULL; 517 struct lock_class_key *key = NULL;
@@ -511,15 +519,17 @@ kernfs_create_file_ns(struct kernfs_node *parent, const char *name,
511#ifdef CONFIG_DEBUG_LOCK_ALLOC 519#ifdef CONFIG_DEBUG_LOCK_ALLOC
512 key = (struct lock_class_key *)&ops->lockdep_key; 520 key = (struct lock_class_key *)&ops->lockdep_key;
513#endif 521#endif
514 return __kernfs_create_file(parent, name, mode, size, ops, priv, ns, 522 return __kernfs_create_file(parent, name, mode, uid, gid,
515 key); 523 size, ops, priv, ns, key);
516} 524}
517 525
518static inline struct kernfs_node * 526static inline struct kernfs_node *
519kernfs_create_file(struct kernfs_node *parent, const char *name, umode_t mode, 527kernfs_create_file(struct kernfs_node *parent, const char *name, umode_t mode,
520 loff_t size, const struct kernfs_ops *ops, void *priv) 528 loff_t size, const struct kernfs_ops *ops, void *priv)
521{ 529{
522 return kernfs_create_file_ns(parent, name, mode, size, ops, priv, NULL); 530 return kernfs_create_file_ns(parent, name, mode,
531 GLOBAL_ROOT_UID, GLOBAL_ROOT_GID,
532 size, ops, priv, NULL);
523} 533}
524 534
525static inline int kernfs_remove_by_name(struct kernfs_node *parent, 535static inline int kernfs_remove_by_name(struct kernfs_node *parent,
diff --git a/kernel/cgroup/cgroup.c b/kernel/cgroup/cgroup.c
index 077370bf8964..35cf3d71f8aa 100644
--- a/kernel/cgroup/cgroup.c
+++ b/kernel/cgroup/cgroup.c
@@ -3557,7 +3557,9 @@ static int cgroup_add_file(struct cgroup_subsys_state *css, struct cgroup *cgrp,
3557 key = &cft->lockdep_key; 3557 key = &cft->lockdep_key;
3558#endif 3558#endif
3559 kn = __kernfs_create_file(cgrp->kn, cgroup_file_name(cgrp, cft, name), 3559 kn = __kernfs_create_file(cgrp->kn, cgroup_file_name(cgrp, cft, name),
3560 cgroup_file_mode(cft), 0, cft->kf_ops, cft, 3560 cgroup_file_mode(cft),
3561 GLOBAL_ROOT_UID, GLOBAL_ROOT_GID,
3562 0, cft->kf_ops, cft,
3561 NULL, key); 3563 NULL, key);
3562 if (IS_ERR(kn)) 3564 if (IS_ERR(kn))
3563 return PTR_ERR(kn); 3565 return PTR_ERR(kn);