1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * fs/sysfs/file.c - sysfs regular (text) file implementation 4 * 5 * Copyright (c) 2001-3 Patrick Mochel 6 * Copyright (c) 2007 SUSE Linux Products GmbH 7 * Copyright (c) 2007 Tejun Heo <teheo@suse.de> 8 * 9 * Please see Documentation/filesystems/sysfs.rst for more information. 10 */ 11 12 #include <linux/module.h> 13 #include <linux/kobject.h> 14 #include <linux/slab.h> 15 #include <linux/list.h> 16 #include <linux/mutex.h> 17 #include <linux/seq_file.h> 18 #include <linux/mm.h> 19 20 #include "sysfs.h" 21 22 static struct kobject *sysfs_file_kobj(struct kernfs_node *kn) 23 { 24 guard(rcu)(); 25 return rcu_dereference(kn->__parent)->priv; 26 } 27 28 /* 29 * Determine ktype->sysfs_ops for the given kernfs_node. This function 30 * must be called while holding an active reference. 31 */ 32 static const struct sysfs_ops *sysfs_file_ops(struct kernfs_node *kn) 33 { 34 struct kobject *kobj = sysfs_file_kobj(kn); 35 36 if (kn->flags & KERNFS_LOCKDEP) 37 lockdep_assert_held(kn); 38 return kobj->ktype ? kobj->ktype->sysfs_ops : NULL; 39 } 40 41 /* 42 * Reads on sysfs are handled through seq_file, which takes care of hairy 43 * details like buffering and seeking. The following function pipes 44 * sysfs_ops->show() result through seq_file. 45 */ 46 static int sysfs_kf_seq_show(struct seq_file *sf, void *v) 47 { 48 struct kernfs_open_file *of = sf->private; 49 struct kobject *kobj = sysfs_file_kobj(of->kn); 50 const struct sysfs_ops *ops = sysfs_file_ops(of->kn); 51 ssize_t count; 52 char *buf; 53 54 if (WARN_ON_ONCE(!ops->show)) 55 return -EINVAL; 56 57 /* acquire buffer and ensure that it's >= PAGE_SIZE and clear */ 58 count = seq_get_buf(sf, &buf); 59 if (count < PAGE_SIZE) { 60 seq_commit(sf, -1); 61 return 0; 62 } 63 memset(buf, 0, PAGE_SIZE); 64 65 count = ops->show(kobj, of->kn->priv, buf); 66 if (count < 0) 67 return count; 68 69 /* 70 * The code works fine with PAGE_SIZE return but it's likely to 71 * indicate truncated result or overflow in normal use cases. 72 */ 73 if (count >= (ssize_t)PAGE_SIZE) { 74 printk("fill_read_buffer: %pS returned bad count\n", 75 ops->show); 76 /* Try to struggle along */ 77 count = PAGE_SIZE - 1; 78 } 79 seq_commit(sf, count); 80 return 0; 81 } 82 83 static ssize_t sysfs_kf_bin_read(struct kernfs_open_file *of, char *buf, 84 size_t count, loff_t pos) 85 { 86 const struct bin_attribute *battr = of->kn->priv; 87 struct kobject *kobj = sysfs_file_kobj(of->kn); 88 loff_t size = file_inode(of->file)->i_size; 89 90 if (!count) 91 return 0; 92 93 if (size) { 94 if (pos >= size) 95 return 0; 96 if (pos + count > size) 97 count = size - pos; 98 } 99 100 if (!battr->read) 101 return -EIO; 102 103 return battr->read(of->file, kobj, battr, buf, pos, count); 104 } 105 106 /* kernfs read callback for regular sysfs files with pre-alloc */ 107 static ssize_t sysfs_kf_read(struct kernfs_open_file *of, char *buf, 108 size_t count, loff_t pos) 109 { 110 const struct sysfs_ops *ops = sysfs_file_ops(of->kn); 111 struct kobject *kobj = sysfs_file_kobj(of->kn); 112 ssize_t len; 113 114 /* 115 * If buf != of->prealloc_buf, we don't know how 116 * large it is, so cannot safely pass it to ->show 117 */ 118 if (WARN_ON_ONCE(buf != of->prealloc_buf)) 119 return 0; 120 len = ops->show(kobj, of->kn->priv, buf); 121 if (len < 0) 122 return len; 123 if (pos) { 124 if (len <= pos) 125 return 0; 126 len -= pos; 127 memmove(buf, buf + pos, len); 128 } 129 return min_t(ssize_t, count, len); 130 } 131 132 /* kernfs write callback for regular sysfs files */ 133 static ssize_t sysfs_kf_write(struct kernfs_open_file *of, char *buf, 134 size_t count, loff_t pos) 135 { 136 const struct sysfs_ops *ops = sysfs_file_ops(of->kn); 137 struct kobject *kobj = sysfs_file_kobj(of->kn); 138 139 if (!count) 140 return 0; 141 142 return ops->store(kobj, of->kn->priv, buf, count); 143 } 144 145 /* kernfs write callback for bin sysfs files */ 146 static ssize_t sysfs_kf_bin_write(struct kernfs_open_file *of, char *buf, 147 size_t count, loff_t pos) 148 { 149 const struct bin_attribute *battr = of->kn->priv; 150 struct kobject *kobj = sysfs_file_kobj(of->kn); 151 loff_t size = file_inode(of->file)->i_size; 152 153 if (size) { 154 if (size <= pos) 155 return -EFBIG; 156 count = min_t(ssize_t, count, size - pos); 157 } 158 if (!count) 159 return 0; 160 161 if (!battr->write) 162 return -EIO; 163 164 return battr->write(of->file, kobj, battr, buf, pos, count); 165 } 166 167 static int sysfs_kf_bin_mmap(struct kernfs_open_file *of, 168 struct vm_area_struct *vma) 169 { 170 const struct bin_attribute *battr = of->kn->priv; 171 struct kobject *kobj = sysfs_file_kobj(of->kn); 172 173 return battr->mmap(of->file, kobj, battr, vma); 174 } 175 176 static loff_t sysfs_kf_bin_llseek(struct kernfs_open_file *of, loff_t offset, 177 int whence) 178 { 179 const struct bin_attribute *battr = of->kn->priv; 180 struct kobject *kobj = sysfs_file_kobj(of->kn); 181 182 if (battr->llseek) 183 return battr->llseek(of->file, kobj, battr, offset, whence); 184 else 185 return generic_file_llseek(of->file, offset, whence); 186 } 187 188 static int sysfs_kf_bin_open(struct kernfs_open_file *of) 189 { 190 const struct bin_attribute *battr = of->kn->priv; 191 192 if (battr->f_mapping) 193 of->file->f_mapping = battr->f_mapping(); 194 195 return 0; 196 } 197 198 void sysfs_notify(struct kobject *kobj, const char *dir, const char *attr) 199 { 200 struct kernfs_node *kn = kobj->sd, *tmp; 201 202 if (kn && dir) 203 kn = kernfs_find_and_get(kn, dir); 204 else 205 kernfs_get(kn); 206 207 if (kn && attr) { 208 tmp = kernfs_find_and_get(kn, attr); 209 kernfs_put(kn); 210 kn = tmp; 211 } 212 213 if (kn) { 214 kernfs_notify(kn); 215 kernfs_put(kn); 216 } 217 } 218 EXPORT_SYMBOL_GPL(sysfs_notify); 219 220 static const struct kernfs_ops sysfs_file_kfops_empty = { 221 }; 222 223 static const struct kernfs_ops sysfs_file_kfops_ro = { 224 .seq_show = sysfs_kf_seq_show, 225 }; 226 227 static const struct kernfs_ops sysfs_file_kfops_wo = { 228 .write = sysfs_kf_write, 229 }; 230 231 static const struct kernfs_ops sysfs_file_kfops_rw = { 232 .seq_show = sysfs_kf_seq_show, 233 .write = sysfs_kf_write, 234 }; 235 236 static const struct kernfs_ops sysfs_prealloc_kfops_ro = { 237 .read = sysfs_kf_read, 238 .prealloc = true, 239 }; 240 241 static const struct kernfs_ops sysfs_prealloc_kfops_wo = { 242 .write = sysfs_kf_write, 243 .prealloc = true, 244 }; 245 246 static const struct kernfs_ops sysfs_prealloc_kfops_rw = { 247 .read = sysfs_kf_read, 248 .write = sysfs_kf_write, 249 .prealloc = true, 250 }; 251 252 static const struct kernfs_ops sysfs_bin_kfops_ro = { 253 .read = sysfs_kf_bin_read, 254 }; 255 256 static const struct kernfs_ops sysfs_bin_kfops_wo = { 257 .write = sysfs_kf_bin_write, 258 }; 259 260 static const struct kernfs_ops sysfs_bin_kfops_rw = { 261 .read = sysfs_kf_bin_read, 262 .write = sysfs_kf_bin_write, 263 }; 264 265 static const struct kernfs_ops sysfs_bin_kfops_mmap = { 266 .read = sysfs_kf_bin_read, 267 .write = sysfs_kf_bin_write, 268 .mmap = sysfs_kf_bin_mmap, 269 .open = sysfs_kf_bin_open, 270 .llseek = sysfs_kf_bin_llseek, 271 }; 272 273 int sysfs_add_file_mode_ns(struct kernfs_node *parent, 274 const struct attribute *attr, umode_t mode, kuid_t uid, 275 kgid_t gid, const void *ns) 276 { 277 struct kobject *kobj = parent->priv; 278 const struct sysfs_ops *sysfs_ops = kobj->ktype->sysfs_ops; 279 struct lock_class_key *key = NULL; 280 const struct kernfs_ops *ops = NULL; 281 struct kernfs_node *kn; 282 283 /* every kobject with an attribute needs a ktype assigned */ 284 if (WARN(!sysfs_ops, KERN_ERR 285 "missing sysfs attribute operations for kobject: %s\n", 286 kobject_name(kobj))) 287 return -EINVAL; 288 289 if (mode & SYSFS_PREALLOC) { 290 if (sysfs_ops->show && sysfs_ops->store) 291 ops = &sysfs_prealloc_kfops_rw; 292 else if (sysfs_ops->show) 293 ops = &sysfs_prealloc_kfops_ro; 294 else if (sysfs_ops->store) 295 ops = &sysfs_prealloc_kfops_wo; 296 } else { 297 if (sysfs_ops->show && sysfs_ops->store) 298 ops = &sysfs_file_kfops_rw; 299 else if (sysfs_ops->show) 300 ops = &sysfs_file_kfops_ro; 301 else if (sysfs_ops->store) 302 ops = &sysfs_file_kfops_wo; 303 } 304 305 if (!ops) 306 ops = &sysfs_file_kfops_empty; 307 308 #ifdef CONFIG_DEBUG_LOCK_ALLOC 309 if (!attr->ignore_lockdep) 310 key = attr->key ?: (struct lock_class_key *)&attr->skey; 311 #endif 312 313 kn = __kernfs_create_file(parent, attr->name, mode & 0777, uid, gid, 314 PAGE_SIZE, ops, (void *)attr, ns, key); 315 if (IS_ERR(kn)) { 316 if (PTR_ERR(kn) == -EEXIST) 317 sysfs_warn_dup(parent, attr->name); 318 return PTR_ERR(kn); 319 } 320 return 0; 321 } 322 323 int sysfs_add_bin_file_mode_ns(struct kernfs_node *parent, 324 const struct bin_attribute *battr, umode_t mode, size_t size, 325 kuid_t uid, kgid_t gid, const void *ns) 326 { 327 const struct attribute *attr = &battr->attr; 328 struct lock_class_key *key = NULL; 329 const struct kernfs_ops *ops; 330 struct kernfs_node *kn; 331 332 if (battr->mmap) 333 ops = &sysfs_bin_kfops_mmap; 334 else if (battr->read && battr->write) 335 ops = &sysfs_bin_kfops_rw; 336 else if (battr->read) 337 ops = &sysfs_bin_kfops_ro; 338 else if (battr->write) 339 ops = &sysfs_bin_kfops_wo; 340 else 341 ops = &sysfs_file_kfops_empty; 342 343 #ifdef CONFIG_DEBUG_LOCK_ALLOC 344 if (!attr->ignore_lockdep) 345 key = attr->key ?: (struct lock_class_key *)&attr->skey; 346 #endif 347 348 kn = __kernfs_create_file(parent, attr->name, mode & 0777, uid, gid, 349 size, ops, (void *)attr, ns, key); 350 if (IS_ERR(kn)) { 351 if (PTR_ERR(kn) == -EEXIST) 352 sysfs_warn_dup(parent, attr->name); 353 return PTR_ERR(kn); 354 } 355 return 0; 356 } 357 358 /** 359 * sysfs_create_file_ns - create an attribute file for an object with custom ns 360 * @kobj: object we're creating for 361 * @attr: attribute descriptor 362 * @ns: namespace the new file should belong to 363 */ 364 int sysfs_create_file_ns(struct kobject *kobj, const struct attribute *attr, 365 const void *ns) 366 { 367 kuid_t uid; 368 kgid_t gid; 369 370 if (WARN_ON(!kobj || !kobj->sd || !attr)) 371 return -EINVAL; 372 373 kobject_get_ownership(kobj, &uid, &gid); 374 return sysfs_add_file_mode_ns(kobj->sd, attr, attr->mode, uid, gid, ns); 375 } 376 EXPORT_SYMBOL_GPL(sysfs_create_file_ns); 377 378 int sysfs_create_files(struct kobject *kobj, const struct attribute * const *ptr) 379 { 380 int err = 0; 381 int i; 382 383 for (i = 0; ptr[i] && !err; i++) 384 err = sysfs_create_file(kobj, ptr[i]); 385 if (err) 386 while (--i >= 0) 387 sysfs_remove_file(kobj, ptr[i]); 388 return err; 389 } 390 EXPORT_SYMBOL_GPL(sysfs_create_files); 391 392 /** 393 * sysfs_add_file_to_group - add an attribute file to a pre-existing group. 394 * @kobj: object we're acting for. 395 * @attr: attribute descriptor. 396 * @group: group name. 397 */ 398 int sysfs_add_file_to_group(struct kobject *kobj, 399 const struct attribute *attr, const char *group) 400 { 401 struct kernfs_node *parent; 402 kuid_t uid; 403 kgid_t gid; 404 int error; 405 406 if (group) { 407 parent = kernfs_find_and_get(kobj->sd, group); 408 } else { 409 parent = kobj->sd; 410 kernfs_get(parent); 411 } 412 413 if (!parent) 414 return -ENOENT; 415 416 kobject_get_ownership(kobj, &uid, &gid); 417 error = sysfs_add_file_mode_ns(parent, attr, attr->mode, uid, gid, 418 NULL); 419 kernfs_put(parent); 420 421 return error; 422 } 423 EXPORT_SYMBOL_GPL(sysfs_add_file_to_group); 424 425 /** 426 * sysfs_chmod_file - update the modified mode value on an object attribute. 427 * @kobj: object we're acting for. 428 * @attr: attribute descriptor. 429 * @mode: file permissions. 430 * 431 */ 432 int sysfs_chmod_file(struct kobject *kobj, const struct attribute *attr, 433 umode_t mode) 434 { 435 struct kernfs_node *kn; 436 struct iattr newattrs; 437 int rc; 438 439 kn = kernfs_find_and_get(kobj->sd, attr->name); 440 if (!kn) 441 return -ENOENT; 442 443 newattrs.ia_mode = (mode & S_IALLUGO) | (kn->mode & ~S_IALLUGO); 444 newattrs.ia_valid = ATTR_MODE; 445 446 rc = kernfs_setattr(kn, &newattrs); 447 448 kernfs_put(kn); 449 return rc; 450 } 451 EXPORT_SYMBOL_GPL(sysfs_chmod_file); 452 453 /** 454 * sysfs_break_active_protection - break "active" protection 455 * @kobj: The kernel object @attr is associated with. 456 * @attr: The attribute to break the "active" protection for. 457 * 458 * With sysfs, just like kernfs, deletion of an attribute is postponed until 459 * all active .show() and .store() callbacks have finished unless this function 460 * is called. Hence this function is useful in methods that implement self 461 * deletion. 462 */ 463 struct kernfs_node *sysfs_break_active_protection(struct kobject *kobj, 464 const struct attribute *attr) 465 { 466 struct kernfs_node *kn; 467 468 kobject_get(kobj); 469 kn = kernfs_find_and_get(kobj->sd, attr->name); 470 if (kn) 471 kernfs_break_active_protection(kn); 472 else 473 kobject_put(kobj); 474 return kn; 475 } 476 EXPORT_SYMBOL_GPL(sysfs_break_active_protection); 477 478 /** 479 * sysfs_unbreak_active_protection - restore "active" protection 480 * @kn: Pointer returned by sysfs_break_active_protection(). 481 * 482 * Undo the effects of sysfs_break_active_protection(). Since this function 483 * calls kernfs_put() on the kernfs node that corresponds to the 'attr' 484 * argument passed to sysfs_break_active_protection() that attribute may have 485 * been removed between the sysfs_break_active_protection() and 486 * sysfs_unbreak_active_protection() calls, it is not safe to access @kn after 487 * this function has returned. 488 */ 489 void sysfs_unbreak_active_protection(struct kernfs_node *kn) 490 { 491 struct kobject *kobj = sysfs_file_kobj(kn); 492 493 kernfs_unbreak_active_protection(kn); 494 kernfs_put(kn); 495 kobject_put(kobj); 496 } 497 EXPORT_SYMBOL_GPL(sysfs_unbreak_active_protection); 498 499 /** 500 * sysfs_remove_file_ns - remove an object attribute with a custom ns tag 501 * @kobj: object we're acting for 502 * @attr: attribute descriptor 503 * @ns: namespace tag of the file to remove 504 * 505 * Hash the attribute name and namespace tag and kill the victim. 506 */ 507 void sysfs_remove_file_ns(struct kobject *kobj, const struct attribute *attr, 508 const void *ns) 509 { 510 struct kernfs_node *parent = kobj->sd; 511 512 kernfs_remove_by_name_ns(parent, attr->name, ns); 513 } 514 EXPORT_SYMBOL_GPL(sysfs_remove_file_ns); 515 516 /** 517 * sysfs_remove_file_self - remove an object attribute from its own method 518 * @kobj: object we're acting for 519 * @attr: attribute descriptor 520 * 521 * See kernfs_remove_self() for details. 522 */ 523 bool sysfs_remove_file_self(struct kobject *kobj, const struct attribute *attr) 524 { 525 struct kernfs_node *parent = kobj->sd; 526 struct kernfs_node *kn; 527 bool ret; 528 529 kn = kernfs_find_and_get(parent, attr->name); 530 if (WARN_ON_ONCE(!kn)) 531 return false; 532 533 ret = kernfs_remove_self(kn); 534 535 kernfs_put(kn); 536 return ret; 537 } 538 EXPORT_SYMBOL_GPL(sysfs_remove_file_self); 539 540 void sysfs_remove_files(struct kobject *kobj, const struct attribute * const *ptr) 541 { 542 int i; 543 544 for (i = 0; ptr[i]; i++) 545 sysfs_remove_file(kobj, ptr[i]); 546 } 547 EXPORT_SYMBOL_GPL(sysfs_remove_files); 548 549 /** 550 * sysfs_remove_file_from_group - remove an attribute file from a group. 551 * @kobj: object we're acting for. 552 * @attr: attribute descriptor. 553 * @group: group name. 554 */ 555 void sysfs_remove_file_from_group(struct kobject *kobj, 556 const struct attribute *attr, const char *group) 557 { 558 struct kernfs_node *parent; 559 560 if (group) { 561 parent = kernfs_find_and_get(kobj->sd, group); 562 } else { 563 parent = kobj->sd; 564 kernfs_get(parent); 565 } 566 567 if (parent) { 568 kernfs_remove_by_name(parent, attr->name); 569 kernfs_put(parent); 570 } 571 } 572 EXPORT_SYMBOL_GPL(sysfs_remove_file_from_group); 573 574 /** 575 * sysfs_create_bin_file - create binary file for object. 576 * @kobj: object. 577 * @attr: attribute descriptor. 578 */ 579 int sysfs_create_bin_file(struct kobject *kobj, 580 const struct bin_attribute *attr) 581 { 582 kuid_t uid; 583 kgid_t gid; 584 585 if (WARN_ON(!kobj || !kobj->sd || !attr)) 586 return -EINVAL; 587 588 kobject_get_ownership(kobj, &uid, &gid); 589 return sysfs_add_bin_file_mode_ns(kobj->sd, attr, attr->attr.mode, 590 attr->size, uid, gid, NULL); 591 } 592 EXPORT_SYMBOL_GPL(sysfs_create_bin_file); 593 594 /** 595 * sysfs_remove_bin_file - remove binary file for object. 596 * @kobj: object. 597 * @attr: attribute descriptor. 598 */ 599 void sysfs_remove_bin_file(struct kobject *kobj, 600 const struct bin_attribute *attr) 601 { 602 kernfs_remove_by_name(kobj->sd, attr->attr.name); 603 } 604 EXPORT_SYMBOL_GPL(sysfs_remove_bin_file); 605 606 static int internal_change_owner(struct kernfs_node *kn, kuid_t kuid, 607 kgid_t kgid) 608 { 609 struct iattr newattrs = { 610 .ia_valid = ATTR_UID | ATTR_GID, 611 .ia_uid = kuid, 612 .ia_gid = kgid, 613 }; 614 return kernfs_setattr(kn, &newattrs); 615 } 616 617 /** 618 * sysfs_link_change_owner - change owner of a sysfs file. 619 * @kobj: object of the kernfs_node the symlink is located in. 620 * @targ: object of the kernfs_node the symlink points to. 621 * @name: name of the link. 622 * @kuid: new owner's kuid 623 * @kgid: new owner's kgid 624 * 625 * This function looks up the sysfs symlink entry @name under @kobj and changes 626 * the ownership to @kuid/@kgid. The symlink is looked up in the namespace of 627 * @targ. 628 * 629 * Returns 0 on success or error code on failure. 630 */ 631 int sysfs_link_change_owner(struct kobject *kobj, struct kobject *targ, 632 const char *name, kuid_t kuid, kgid_t kgid) 633 { 634 struct kernfs_node *kn = NULL; 635 int error; 636 637 if (!name || !kobj->state_in_sysfs || !targ->state_in_sysfs) 638 return -EINVAL; 639 640 error = -ENOENT; 641 kn = kernfs_find_and_get_ns(kobj->sd, name, targ->sd->ns); 642 if (!kn) 643 goto out; 644 645 error = -EINVAL; 646 if (kernfs_type(kn) != KERNFS_LINK) 647 goto out; 648 if (kn->symlink.target_kn->priv != targ) 649 goto out; 650 651 error = internal_change_owner(kn, kuid, kgid); 652 653 out: 654 kernfs_put(kn); 655 return error; 656 } 657 658 /** 659 * sysfs_file_change_owner - change owner of a sysfs file. 660 * @kobj: object. 661 * @name: name of the file to change. 662 * @kuid: new owner's kuid 663 * @kgid: new owner's kgid 664 * 665 * This function looks up the sysfs entry @name under @kobj and changes the 666 * ownership to @kuid/@kgid. 667 * 668 * Returns 0 on success or error code on failure. 669 */ 670 int sysfs_file_change_owner(struct kobject *kobj, const char *name, kuid_t kuid, 671 kgid_t kgid) 672 { 673 struct kernfs_node *kn; 674 int error; 675 676 if (!name) 677 return -EINVAL; 678 679 if (!kobj->state_in_sysfs) 680 return -EINVAL; 681 682 kn = kernfs_find_and_get(kobj->sd, name); 683 if (!kn) 684 return -ENOENT; 685 686 error = internal_change_owner(kn, kuid, kgid); 687 688 kernfs_put(kn); 689 690 return error; 691 } 692 EXPORT_SYMBOL_GPL(sysfs_file_change_owner); 693 694 /** 695 * sysfs_change_owner - change owner of the given object. 696 * @kobj: object. 697 * @kuid: new owner's kuid 698 * @kgid: new owner's kgid 699 * 700 * Change the owner of the default directory, files, groups, and attributes of 701 * @kobj to @kuid/@kgid. Note that sysfs_change_owner mirrors how the sysfs 702 * entries for a kobject are added by driver core. In summary, 703 * sysfs_change_owner() takes care of the default directory entry for @kobj, 704 * the default attributes associated with the ktype of @kobj and the default 705 * attributes associated with the ktype of @kobj. 706 * Additional properties not added by driver core have to be changed by the 707 * driver or subsystem which created them. This is similar to how 708 * driver/subsystem specific entries are removed. 709 * 710 * Returns 0 on success or error code on failure. 711 */ 712 int sysfs_change_owner(struct kobject *kobj, kuid_t kuid, kgid_t kgid) 713 { 714 int error; 715 const struct kobj_type *ktype; 716 717 if (!kobj->state_in_sysfs) 718 return -EINVAL; 719 720 /* Change the owner of the kobject itself. */ 721 error = internal_change_owner(kobj->sd, kuid, kgid); 722 if (error) 723 return error; 724 725 ktype = get_ktype(kobj); 726 if (ktype) { 727 /* 728 * Change owner of the default groups associated with the 729 * ktype of @kobj. 730 */ 731 error = sysfs_groups_change_owner(kobj, ktype->default_groups, 732 kuid, kgid); 733 if (error) 734 return error; 735 } 736 737 return 0; 738 } 739 EXPORT_SYMBOL_GPL(sysfs_change_owner); 740 741 /** 742 * sysfs_emit - scnprintf equivalent, aware of PAGE_SIZE buffer. 743 * @buf: start of PAGE_SIZE buffer. 744 * @fmt: format 745 * @...: optional arguments to @format 746 * 747 * 748 * Returns number of characters written to @buf. 749 */ 750 int sysfs_emit(char *buf, const char *fmt, ...) 751 { 752 va_list args; 753 int len; 754 755 if (WARN(!buf || offset_in_page(buf), 756 "invalid sysfs_emit: buf:%p\n", buf)) 757 return 0; 758 759 va_start(args, fmt); 760 len = vscnprintf(buf, PAGE_SIZE, fmt, args); 761 va_end(args); 762 763 return len; 764 } 765 EXPORT_SYMBOL_GPL(sysfs_emit); 766 767 /** 768 * sysfs_emit_at - scnprintf equivalent, aware of PAGE_SIZE buffer. 769 * @buf: start of PAGE_SIZE buffer. 770 * @at: offset in @buf to start write in bytes 771 * @at must be >= 0 && < PAGE_SIZE 772 * @fmt: format 773 * @...: optional arguments to @fmt 774 * 775 * 776 * Returns number of characters written starting at &@buf[@at]. 777 */ 778 int sysfs_emit_at(char *buf, int at, const char *fmt, ...) 779 { 780 va_list args; 781 int len; 782 783 if (WARN(!buf || offset_in_page(buf) || at < 0 || at >= PAGE_SIZE, 784 "invalid sysfs_emit_at: buf:%p at:%d\n", buf, at)) 785 return 0; 786 787 va_start(args, fmt); 788 len = vscnprintf(buf + at, PAGE_SIZE - at, fmt, args); 789 va_end(args); 790 791 return len; 792 } 793 EXPORT_SYMBOL_GPL(sysfs_emit_at); 794 795 /** 796 * sysfs_bin_attr_simple_read - read callback to simply copy from memory. 797 * @file: attribute file which is being read. 798 * @kobj: object to which the attribute belongs. 799 * @attr: attribute descriptor. 800 * @buf: destination buffer. 801 * @off: offset in bytes from which to read. 802 * @count: maximum number of bytes to read. 803 * 804 * Simple ->read() callback for bin_attributes backed by a buffer in memory. 805 * The @private and @size members in struct bin_attribute must be set to the 806 * buffer's location and size before the bin_attribute is created in sysfs. 807 * 808 * Bounds check for @off and @count is done in sysfs_kf_bin_read(). 809 * Negative value check for @off is done in vfs_setpos() and default_llseek(). 810 * 811 * Returns number of bytes written to @buf. 812 */ 813 ssize_t sysfs_bin_attr_simple_read(struct file *file, struct kobject *kobj, 814 const struct bin_attribute *attr, char *buf, 815 loff_t off, size_t count) 816 { 817 memcpy(buf, attr->private + off, count); 818 return count; 819 } 820 EXPORT_SYMBOL_GPL(sysfs_bin_attr_simple_read); 821