hc
2024-02-20 102a0743326a03cd1a1202ceda21e175b7d3575c
kernel/fs/sysfs/group.c
....@@ -13,6 +13,7 @@
1313 #include <linux/dcache.h>
1414 #include <linux/namei.h>
1515 #include <linux/err.h>
16
+#include <linux/fs.h>
1617 #include "sysfs.h"
1718
1819
....@@ -112,7 +113,8 @@
112113 kgid_t gid;
113114 int error;
114115
115
- BUG_ON(!kobj || (!update && !kobj->sd));
116
+ if (WARN_ON(!kobj || (!update && !kobj->sd)))
117
+ return -EINVAL;
116118
117119 /* Updates may happen before the object has been instantiated */
118120 if (unlikely(update && !kobj->sd))
....@@ -174,6 +176,26 @@
174176 }
175177 EXPORT_SYMBOL_GPL(sysfs_create_group);
176178
179
+static int internal_create_groups(struct kobject *kobj, int update,
180
+ const struct attribute_group **groups)
181
+{
182
+ int error = 0;
183
+ int i;
184
+
185
+ if (!groups)
186
+ return 0;
187
+
188
+ for (i = 0; groups[i]; i++) {
189
+ error = internal_create_group(kobj, update, groups[i]);
190
+ if (error) {
191
+ while (--i >= 0)
192
+ sysfs_remove_group(kobj, groups[i]);
193
+ break;
194
+ }
195
+ }
196
+ return error;
197
+}
198
+
177199 /**
178200 * sysfs_create_groups - given a directory kobject, create a bunch of attribute groups
179201 * @kobj: The kobject to create the group on
....@@ -190,23 +212,27 @@
190212 int sysfs_create_groups(struct kobject *kobj,
191213 const struct attribute_group **groups)
192214 {
193
- int error = 0;
194
- int i;
195
-
196
- if (!groups)
197
- return 0;
198
-
199
- for (i = 0; groups[i]; i++) {
200
- error = sysfs_create_group(kobj, groups[i]);
201
- if (error) {
202
- while (--i >= 0)
203
- sysfs_remove_group(kobj, groups[i]);
204
- break;
205
- }
206
- }
207
- return error;
215
+ return internal_create_groups(kobj, 0, groups);
208216 }
209217 EXPORT_SYMBOL_GPL(sysfs_create_groups);
218
+
219
+/**
220
+ * sysfs_update_groups - given a directory kobject, create a bunch of attribute groups
221
+ * @kobj: The kobject to update the group on
222
+ * @groups: The attribute groups to update, NULL terminated
223
+ *
224
+ * This function update a bunch of attribute groups. If an error occurs when
225
+ * updating a group, all previously updated groups will be removed together
226
+ * with already existing (not updated) attributes.
227
+ *
228
+ * Returns 0 on success or error code from sysfs_update_group on failure.
229
+ */
230
+int sysfs_update_groups(struct kobject *kobj,
231
+ const struct attribute_group **groups)
232
+{
233
+ return internal_create_groups(kobj, 1, groups);
234
+}
235
+EXPORT_SYMBOL_GPL(sysfs_update_groups);
210236
211237 /**
212238 * sysfs_update_group - given a directory kobject, update an attribute group
....@@ -390,15 +416,18 @@
390416 EXPORT_SYMBOL_GPL(sysfs_remove_link_from_group);
391417
392418 /**
393
- * __compat_only_sysfs_link_entry_to_kobj - add a symlink to a kobject pointing
419
+ * compat_only_sysfs_link_entry_to_kobj - add a symlink to a kobject pointing
394420 * to a group or an attribute
395421 * @kobj: The kobject containing the group.
396422 * @target_kobj: The target kobject.
397423 * @target_name: The name of the target group or attribute.
424
+ * @symlink_name: The name of the symlink file (target_name will be
425
+ * considered if symlink_name is NULL).
398426 */
399
-int __compat_only_sysfs_link_entry_to_kobj(struct kobject *kobj,
400
- struct kobject *target_kobj,
401
- const char *target_name)
427
+int compat_only_sysfs_link_entry_to_kobj(struct kobject *kobj,
428
+ struct kobject *target_kobj,
429
+ const char *target_name,
430
+ const char *symlink_name)
402431 {
403432 struct kernfs_node *target;
404433 struct kernfs_node *entry;
....@@ -423,12 +452,129 @@
423452 return -ENOENT;
424453 }
425454
426
- link = kernfs_create_link(kobj->sd, target_name, entry);
427
- if (IS_ERR(link) && PTR_ERR(link) == -EEXIST)
428
- sysfs_warn_dup(kobj->sd, target_name);
455
+ if (!symlink_name)
456
+ symlink_name = target_name;
457
+
458
+ link = kernfs_create_link(kobj->sd, symlink_name, entry);
459
+ if (PTR_ERR(link) == -EEXIST)
460
+ sysfs_warn_dup(kobj->sd, symlink_name);
429461
430462 kernfs_put(entry);
431463 kernfs_put(target);
432464 return PTR_ERR_OR_ZERO(link);
433465 }
434
-EXPORT_SYMBOL_GPL(__compat_only_sysfs_link_entry_to_kobj);
466
+EXPORT_SYMBOL_GPL(compat_only_sysfs_link_entry_to_kobj);
467
+
468
+static int sysfs_group_attrs_change_owner(struct kernfs_node *grp_kn,
469
+ const struct attribute_group *grp,
470
+ struct iattr *newattrs)
471
+{
472
+ struct kernfs_node *kn;
473
+ int error;
474
+
475
+ if (grp->attrs) {
476
+ struct attribute *const *attr;
477
+
478
+ for (attr = grp->attrs; *attr; attr++) {
479
+ kn = kernfs_find_and_get(grp_kn, (*attr)->name);
480
+ if (!kn)
481
+ return -ENOENT;
482
+
483
+ error = kernfs_setattr(kn, newattrs);
484
+ kernfs_put(kn);
485
+ if (error)
486
+ return error;
487
+ }
488
+ }
489
+
490
+ if (grp->bin_attrs) {
491
+ struct bin_attribute *const *bin_attr;
492
+
493
+ for (bin_attr = grp->bin_attrs; *bin_attr; bin_attr++) {
494
+ kn = kernfs_find_and_get(grp_kn, (*bin_attr)->attr.name);
495
+ if (!kn)
496
+ return -ENOENT;
497
+
498
+ error = kernfs_setattr(kn, newattrs);
499
+ kernfs_put(kn);
500
+ if (error)
501
+ return error;
502
+ }
503
+ }
504
+
505
+ return 0;
506
+}
507
+
508
+/**
509
+ * sysfs_group_change_owner - change owner of an attribute group.
510
+ * @kobj: The kobject containing the group.
511
+ * @grp: The attribute group.
512
+ * @kuid: new owner's kuid
513
+ * @kgid: new owner's kgid
514
+ *
515
+ * Returns 0 on success or error code on failure.
516
+ */
517
+int sysfs_group_change_owner(struct kobject *kobj,
518
+ const struct attribute_group *grp, kuid_t kuid,
519
+ kgid_t kgid)
520
+{
521
+ struct kernfs_node *grp_kn;
522
+ int error;
523
+ struct iattr newattrs = {
524
+ .ia_valid = ATTR_UID | ATTR_GID,
525
+ .ia_uid = kuid,
526
+ .ia_gid = kgid,
527
+ };
528
+
529
+ if (!kobj->state_in_sysfs)
530
+ return -EINVAL;
531
+
532
+ if (grp->name) {
533
+ grp_kn = kernfs_find_and_get(kobj->sd, grp->name);
534
+ } else {
535
+ kernfs_get(kobj->sd);
536
+ grp_kn = kobj->sd;
537
+ }
538
+ if (!grp_kn)
539
+ return -ENOENT;
540
+
541
+ error = kernfs_setattr(grp_kn, &newattrs);
542
+ if (!error)
543
+ error = sysfs_group_attrs_change_owner(grp_kn, grp, &newattrs);
544
+
545
+ kernfs_put(grp_kn);
546
+
547
+ return error;
548
+}
549
+EXPORT_SYMBOL_GPL(sysfs_group_change_owner);
550
+
551
+/**
552
+ * sysfs_groups_change_owner - change owner of a set of attribute groups.
553
+ * @kobj: The kobject containing the groups.
554
+ * @groups: The attribute groups.
555
+ * @kuid: new owner's kuid
556
+ * @kgid: new owner's kgid
557
+ *
558
+ * Returns 0 on success or error code on failure.
559
+ */
560
+int sysfs_groups_change_owner(struct kobject *kobj,
561
+ const struct attribute_group **groups,
562
+ kuid_t kuid, kgid_t kgid)
563
+{
564
+ int error = 0, i;
565
+
566
+ if (!kobj->state_in_sysfs)
567
+ return -EINVAL;
568
+
569
+ if (!groups)
570
+ return 0;
571
+
572
+ for (i = 0; groups[i]; i++) {
573
+ error = sysfs_group_change_owner(kobj, groups[i], kuid, kgid);
574
+ if (error)
575
+ break;
576
+ }
577
+
578
+ return error;
579
+}
580
+EXPORT_SYMBOL_GPL(sysfs_groups_change_owner);