Skip to content

Commit 083f9fa

Browse files
committed
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
2 parents 91fff6f + 67510d7 commit 083f9fa

File tree

4 files changed

+77
-40
lines changed

4 files changed

+77
-40
lines changed

drivers/base/topology.c

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,19 +27,35 @@ static ssize_t name##_read(struct file *file, struct kobject *kobj, \
2727
loff_t off, size_t count) \
2828
{ \
2929
struct device *dev = kobj_to_dev(kobj); \
30+
cpumask_var_t mask; \
31+
ssize_t n; \
3032
\
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; \
3341
} \
3442
\
3543
static ssize_t name##_list_read(struct file *file, struct kobject *kobj, \
3644
const struct bin_attribute *attr, char *buf, \
3745
loff_t off, size_t count) \
3846
{ \
3947
struct device *dev = kobj_to_dev(kobj); \
48+
cpumask_var_t mask; \
49+
ssize_t n; \
50+
\
51+
if (!alloc_cpumask_var(&mask, GFP_KERNEL)) \
52+
return -ENOMEM; \
53+
\
54+
cpumask_copy(mask, topology_##mask(dev->id)); \
55+
n = cpumap_print_list_to_buf(buf, mask, off, count); \
56+
free_cpumask_var(mask); \
4057
\
41-
return cpumap_print_list_to_buf(buf, topology_##mask(dev->id), \
42-
off, count); \
58+
return n; \
4359
}
4460

4561
define_id_show_func(physical_package_id, "%d");

fs/debugfs/file.c

Lines changed: 51 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -64,22 +64,13 @@ const struct file_operations *debugfs_real_fops(const struct file *filp)
6464
}
6565
EXPORT_SYMBOL_GPL(debugfs_real_fops);
6666

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)
8374
{
8475
struct debugfs_fsdata *fsd;
8576
void *d_fsd;
@@ -96,15 +87,17 @@ int debugfs_file_get(struct dentry *dentry)
9687
if (!((unsigned long)d_fsd & DEBUGFS_FSDATA_IS_REAL_FOPS_BIT)) {
9788
fsd = d_fsd;
9889
} else {
90+
if (WARN_ON(mode == DBGFS_GET_ALREADY))
91+
return -EINVAL;
92+
9993
fsd = kmalloc(sizeof(*fsd), GFP_KERNEL);
10094
if (!fsd)
10195
return -ENOMEM;
10296

103-
if ((unsigned long)d_fsd & DEBUGFS_FSDATA_IS_SHORT_FOPS_BIT) {
97+
if (mode == DBGFS_GET_SHORT) {
10498
fsd->real_fops = NULL;
10599
fsd->short_fops = (void *)((unsigned long)d_fsd &
106-
~(DEBUGFS_FSDATA_IS_REAL_FOPS_BIT |
107-
DEBUGFS_FSDATA_IS_SHORT_FOPS_BIT));
100+
~DEBUGFS_FSDATA_IS_REAL_FOPS_BIT);
108101
} else {
109102
fsd->real_fops = (void *)((unsigned long)d_fsd &
110103
~DEBUGFS_FSDATA_IS_REAL_FOPS_BIT);
@@ -138,6 +131,26 @@ int debugfs_file_get(struct dentry *dentry)
138131

139132
return 0;
140133
}
134+
135+
/**
136+
* debugfs_file_get - mark the beginning of file data access
137+
* @dentry: the dentry object whose data is being accessed.
138+
*
139+
* Up to a matching call to debugfs_file_put(), any successive call
140+
* into the file removing functions debugfs_remove() and
141+
* debugfs_remove_recursive() will block. Since associated private
142+
* file data may only get freed after a successful return of any of
143+
* the removal functions, you may safely access it after a successful
144+
* call to debugfs_file_get() without worrying about lifetime issues.
145+
*
146+
* If -%EIO is returned, the file has already been removed and thus,
147+
* it is not safe to access any of its data. If, on the other hand,
148+
* it is allowed to access the file data, zero is returned.
149+
*/
150+
int debugfs_file_get(struct dentry *dentry)
151+
{
152+
return __debugfs_file_get(dentry, DBGFS_GET_ALREADY);
153+
}
141154
EXPORT_SYMBOL_GPL(debugfs_file_get);
142155

143156
/**
@@ -267,7 +280,7 @@ static int open_proxy_open(struct inode *inode, struct file *filp)
267280
const struct file_operations *real_fops = NULL;
268281
int r;
269282

270-
r = debugfs_file_get(dentry);
283+
r = __debugfs_file_get(dentry, DBGFS_GET_REGULAR);
271284
if (r)
272285
return r == -EIO ? -ENOENT : r;
273286

@@ -424,15 +437,16 @@ static void __full_proxy_fops_init(struct file_operations *proxy_fops,
424437
proxy_fops->unlocked_ioctl = full_proxy_unlocked_ioctl;
425438
}
426439

427-
static int full_proxy_open(struct inode *inode, struct file *filp)
440+
static int full_proxy_open(struct inode *inode, struct file *filp,
441+
enum dbgfs_get_mode mode)
428442
{
429443
struct dentry *dentry = F_DENTRY(filp);
430444
const struct file_operations *real_fops;
431445
struct file_operations *proxy_fops = NULL;
432446
struct debugfs_fsdata *fsd;
433447
int r;
434448

435-
r = debugfs_file_get(dentry);
449+
r = __debugfs_file_get(dentry, mode);
436450
if (r)
437451
return r == -EIO ? -ENOENT : r;
438452

@@ -491,8 +505,22 @@ static int full_proxy_open(struct inode *inode, struct file *filp)
491505
return r;
492506
}
493507

508+
static int full_proxy_open_regular(struct inode *inode, struct file *filp)
509+
{
510+
return full_proxy_open(inode, filp, DBGFS_GET_REGULAR);
511+
}
512+
494513
const struct file_operations debugfs_full_proxy_file_operations = {
495-
.open = full_proxy_open,
514+
.open = full_proxy_open_regular,
515+
};
516+
517+
static int full_proxy_open_short(struct inode *inode, struct file *filp)
518+
{
519+
return full_proxy_open(inode, filp, DBGFS_GET_SHORT);
520+
}
521+
522+
const struct file_operations debugfs_full_short_proxy_file_operations = {
523+
.open = full_proxy_open_short,
496524
};
497525

498526
ssize_t debugfs_attr_read(struct file *file, char __user *buf,

fs/debugfs/inode.c

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -229,7 +229,7 @@ static void debugfs_release_dentry(struct dentry *dentry)
229229
return;
230230

231231
/* 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)) {
233233
WARN_ON(!list_empty(&fsd->cancellations));
234234
mutex_destroy(&fsd->cancellations_mtx);
235235
}
@@ -455,8 +455,7 @@ struct dentry *debugfs_create_file_full(const char *name, umode_t mode,
455455
const struct file_operations *fops)
456456
{
457457
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))
460459
return ERR_PTR(-EINVAL);
461460

462461
return __debugfs_create_file(name, mode, parent, data,
@@ -471,15 +470,13 @@ struct dentry *debugfs_create_file_short(const char *name, umode_t mode,
471470
const struct debugfs_short_fops *fops)
472471
{
473472
if (WARN_ON((unsigned long)fops &
474-
(DEBUGFS_FSDATA_IS_SHORT_FOPS_BIT |
475-
DEBUGFS_FSDATA_IS_REAL_FOPS_BIT)))
473+
DEBUGFS_FSDATA_IS_REAL_FOPS_BIT))
476474
return ERR_PTR(-EINVAL);
477475

478476
return __debugfs_create_file(name, mode, parent, data,
479-
fops ? &debugfs_full_proxy_file_operations :
477+
fops ? &debugfs_full_short_proxy_file_operations :
480478
&debugfs_noop_file_operations,
481-
(const void *)((unsigned long)fops |
482-
DEBUGFS_FSDATA_IS_SHORT_FOPS_BIT));
479+
fops);
483480
}
484481
EXPORT_SYMBOL_GPL(debugfs_create_file_short);
485482

fs/debugfs/internal.h

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ struct file_operations;
1515
extern const struct file_operations debugfs_noop_file_operations;
1616
extern const struct file_operations debugfs_open_proxy_file_operations;
1717
extern const struct file_operations debugfs_full_proxy_file_operations;
18+
extern const struct file_operations debugfs_full_short_proxy_file_operations;
1819

1920
struct debugfs_fsdata {
2021
const struct file_operations *real_fops;
@@ -40,11 +41,6 @@ struct debugfs_fsdata {
4041
* pointer gets its lowest bit set.
4142
*/
4243
#define DEBUGFS_FSDATA_IS_REAL_FOPS_BIT BIT(0)
43-
/*
44-
* A dentry's ->d_fsdata, when pointing to real fops, is with
45-
* short fops instead of full fops.
46-
*/
47-
#define DEBUGFS_FSDATA_IS_SHORT_FOPS_BIT BIT(1)
4844

4945
/* Access BITS */
5046
#define DEBUGFS_ALLOW_API BIT(0)

0 commit comments

Comments
 (0)