Merge tag 'driver-core-6.13-rc7' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core

Pull driver core and debugfs fixes from Greg KH:
"Here are some small driver core and debugfs fixes that resolve some
reported problems:

- debugfs runtime error reporting fixes

- topology cpumask race-condition fix

- MAINTAINERS file email update

All of these have been in linux-next this week with no reported
issues"

* tag 'driver-core-6.13-rc7' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core:
fs: debugfs: fix open proxy for unsafe files
MAINTAINERS: align Danilo's maintainer entries
topology: Keep the cpumask unchanged when printing cpumap
debugfs: fix missing mutex_destroy() in short_fops case
fs: debugfs: differentiate short fops with proxy ops

Changed files
+77 -40
drivers
base
fs
+20 -4
drivers/base/topology.c
··· 27 27 loff_t off, size_t count) \ 28 28 { \ 29 29 struct device *dev = kobj_to_dev(kobj); \ 30 + cpumask_var_t mask; \ 31 + ssize_t n; \ 30 32 \ 31 - return cpumap_print_bitmask_to_buf(buf, topology_##mask(dev->id), \ 32 - off, count); \ 33 + if (!alloc_cpumask_var(&mask, GFP_KERNEL)) \ 34 + return -ENOMEM; \ 35 + \ 36 + cpumask_copy(mask, topology_##mask(dev->id)); \ 37 + n = cpumap_print_bitmask_to_buf(buf, mask, off, count); \ 38 + free_cpumask_var(mask); \ 39 + \ 40 + return n; \ 33 41 } \ 34 42 \ 35 43 static ssize_t name##_list_read(struct file *file, struct kobject *kobj, \ ··· 45 37 loff_t off, size_t count) \ 46 38 { \ 47 39 struct device *dev = kobj_to_dev(kobj); \ 40 + cpumask_var_t mask; \ 41 + ssize_t n; \ 48 42 \ 49 - return cpumap_print_list_to_buf(buf, topology_##mask(dev->id), \ 50 - off, count); \ 43 + if (!alloc_cpumask_var(&mask, GFP_KERNEL)) \ 44 + return -ENOMEM; \ 45 + \ 46 + cpumask_copy(mask, topology_##mask(dev->id)); \ 47 + n = cpumap_print_list_to_buf(buf, mask, off, count); \ 48 + free_cpumask_var(mask); \ 49 + \ 50 + return n; \ 51 51 } 52 52 53 53 define_id_show_func(physical_package_id, "%d");
+51 -23
fs/debugfs/file.c
··· 64 64 } 65 65 EXPORT_SYMBOL_GPL(debugfs_real_fops); 66 66 67 - /** 68 - * debugfs_file_get - mark the beginning of file data access 69 - * @dentry: the dentry object whose data is being accessed. 70 - * 71 - * Up to a matching call to debugfs_file_put(), any successive call 72 - * into the file removing functions debugfs_remove() and 73 - * debugfs_remove_recursive() will block. Since associated private 74 - * file data may only get freed after a successful return of any of 75 - * the removal functions, you may safely access it after a successful 76 - * call to debugfs_file_get() without worrying about lifetime issues. 77 - * 78 - * If -%EIO is returned, the file has already been removed and thus, 79 - * it is not safe to access any of its data. If, on the other hand, 80 - * it is allowed to access the file data, zero is returned. 81 - */ 82 - int debugfs_file_get(struct dentry *dentry) 67 + enum dbgfs_get_mode { 68 + DBGFS_GET_ALREADY, 69 + DBGFS_GET_REGULAR, 70 + DBGFS_GET_SHORT, 71 + }; 72 + 73 + static int __debugfs_file_get(struct dentry *dentry, enum dbgfs_get_mode mode) 83 74 { 84 75 struct debugfs_fsdata *fsd; 85 76 void *d_fsd; ··· 87 96 if (!((unsigned long)d_fsd & DEBUGFS_FSDATA_IS_REAL_FOPS_BIT)) { 88 97 fsd = d_fsd; 89 98 } else { 99 + if (WARN_ON(mode == DBGFS_GET_ALREADY)) 100 + return -EINVAL; 101 + 90 102 fsd = kmalloc(sizeof(*fsd), GFP_KERNEL); 91 103 if (!fsd) 92 104 return -ENOMEM; 93 105 94 - if ((unsigned long)d_fsd & DEBUGFS_FSDATA_IS_SHORT_FOPS_BIT) { 106 + if (mode == DBGFS_GET_SHORT) { 95 107 fsd->real_fops = NULL; 96 108 fsd->short_fops = (void *)((unsigned long)d_fsd & 97 - ~(DEBUGFS_FSDATA_IS_REAL_FOPS_BIT | 98 - DEBUGFS_FSDATA_IS_SHORT_FOPS_BIT)); 109 + ~DEBUGFS_FSDATA_IS_REAL_FOPS_BIT); 99 110 } else { 100 111 fsd->real_fops = (void *)((unsigned long)d_fsd & 101 112 ~DEBUGFS_FSDATA_IS_REAL_FOPS_BIT); ··· 130 137 return -EIO; 131 138 132 139 return 0; 140 + } 141 + 142 + /** 143 + * debugfs_file_get - mark the beginning of file data access 144 + * @dentry: the dentry object whose data is being accessed. 145 + * 146 + * Up to a matching call to debugfs_file_put(), any successive call 147 + * into the file removing functions debugfs_remove() and 148 + * debugfs_remove_recursive() will block. Since associated private 149 + * file data may only get freed after a successful return of any of 150 + * the removal functions, you may safely access it after a successful 151 + * call to debugfs_file_get() without worrying about lifetime issues. 152 + * 153 + * If -%EIO is returned, the file has already been removed and thus, 154 + * it is not safe to access any of its data. If, on the other hand, 155 + * it is allowed to access the file data, zero is returned. 156 + */ 157 + int debugfs_file_get(struct dentry *dentry) 158 + { 159 + return __debugfs_file_get(dentry, DBGFS_GET_ALREADY); 133 160 } 134 161 EXPORT_SYMBOL_GPL(debugfs_file_get); 135 162 ··· 280 267 const struct file_operations *real_fops = NULL; 281 268 int r; 282 269 283 - r = debugfs_file_get(dentry); 270 + r = __debugfs_file_get(dentry, DBGFS_GET_REGULAR); 284 271 if (r) 285 272 return r == -EIO ? -ENOENT : r; 286 273 ··· 437 424 proxy_fops->unlocked_ioctl = full_proxy_unlocked_ioctl; 438 425 } 439 426 440 - static int full_proxy_open(struct inode *inode, struct file *filp) 427 + static int full_proxy_open(struct inode *inode, struct file *filp, 428 + enum dbgfs_get_mode mode) 441 429 { 442 430 struct dentry *dentry = F_DENTRY(filp); 443 431 const struct file_operations *real_fops; ··· 446 432 struct debugfs_fsdata *fsd; 447 433 int r; 448 434 449 - r = debugfs_file_get(dentry); 435 + r = __debugfs_file_get(dentry, mode); 450 436 if (r) 451 437 return r == -EIO ? -ENOENT : r; 452 438 ··· 505 491 return r; 506 492 } 507 493 494 + static int full_proxy_open_regular(struct inode *inode, struct file *filp) 495 + { 496 + return full_proxy_open(inode, filp, DBGFS_GET_REGULAR); 497 + } 498 + 508 499 const struct file_operations debugfs_full_proxy_file_operations = { 509 - .open = full_proxy_open, 500 + .open = full_proxy_open_regular, 501 + }; 502 + 503 + static int full_proxy_open_short(struct inode *inode, struct file *filp) 504 + { 505 + return full_proxy_open(inode, filp, DBGFS_GET_SHORT); 506 + } 507 + 508 + const struct file_operations debugfs_full_short_proxy_file_operations = { 509 + .open = full_proxy_open_short, 510 510 }; 511 511 512 512 ssize_t debugfs_attr_read(struct file *file, char __user *buf,
+5 -8
fs/debugfs/inode.c
··· 229 229 return; 230 230 231 231 /* check it wasn't a dir (no fsdata) or automount (no real_fops) */ 232 - if (fsd && fsd->real_fops) { 232 + if (fsd && (fsd->real_fops || fsd->short_fops)) { 233 233 WARN_ON(!list_empty(&fsd->cancellations)); 234 234 mutex_destroy(&fsd->cancellations_mtx); 235 235 } ··· 455 455 const struct file_operations *fops) 456 456 { 457 457 if (WARN_ON((unsigned long)fops & 458 - (DEBUGFS_FSDATA_IS_SHORT_FOPS_BIT | 459 - DEBUGFS_FSDATA_IS_REAL_FOPS_BIT))) 458 + DEBUGFS_FSDATA_IS_REAL_FOPS_BIT)) 460 459 return ERR_PTR(-EINVAL); 461 460 462 461 return __debugfs_create_file(name, mode, parent, data, ··· 470 471 const struct debugfs_short_fops *fops) 471 472 { 472 473 if (WARN_ON((unsigned long)fops & 473 - (DEBUGFS_FSDATA_IS_SHORT_FOPS_BIT | 474 - DEBUGFS_FSDATA_IS_REAL_FOPS_BIT))) 474 + DEBUGFS_FSDATA_IS_REAL_FOPS_BIT)) 475 475 return ERR_PTR(-EINVAL); 476 476 477 477 return __debugfs_create_file(name, mode, parent, data, 478 - fops ? &debugfs_full_proxy_file_operations : 478 + fops ? &debugfs_full_short_proxy_file_operations : 479 479 &debugfs_noop_file_operations, 480 - (const void *)((unsigned long)fops | 481 - DEBUGFS_FSDATA_IS_SHORT_FOPS_BIT)); 480 + fops); 482 481 } 483 482 EXPORT_SYMBOL_GPL(debugfs_create_file_short); 484 483
+1 -5
fs/debugfs/internal.h
··· 15 15 extern const struct file_operations debugfs_noop_file_operations; 16 16 extern const struct file_operations debugfs_open_proxy_file_operations; 17 17 extern const struct file_operations debugfs_full_proxy_file_operations; 18 + extern const struct file_operations debugfs_full_short_proxy_file_operations; 18 19 19 20 struct debugfs_fsdata { 20 21 const struct file_operations *real_fops; ··· 41 40 * pointer gets its lowest bit set. 42 41 */ 43 42 #define DEBUGFS_FSDATA_IS_REAL_FOPS_BIT BIT(0) 44 - /* 45 - * A dentry's ->d_fsdata, when pointing to real fops, is with 46 - * short fops instead of full fops. 47 - */ 48 - #define DEBUGFS_FSDATA_IS_SHORT_FOPS_BIT BIT(1) 49 43 50 44 /* Access BITS */ 51 45 #define DEBUGFS_ALLOW_API BIT(0)