Skip to content

Commit f30e0ef

Browse files
nabijaczleweliRageLtMan
authored andcommitted
linux/spl: base proc_dohostid() on proc_dostring()
This fixes /proc/sys/kernel/spl/hostid on kernels with mainline commit 32927393dc1ccd60fb2bdc05b9e8e88753761469 ("sysctl: pass kernel pointers to ->proc_handler") ‒ 5.7-rc1 and up The access_ok() check in copy_to_user() in proc_copyout_string() would always fail, so all userspace reads and writes would fail with EINVAL proc_dostring() strips only the final new-line, but simple_strtoul() doesn't actually need a back-trimmed string ‒ writing "012345678 \n" is still allowed, as is "012345678zupsko", &c. This alters what happens when an invalid value is written ‒ previously it'd get set to what-ever simple_strtoul() returned (probably 0, thereby resetting it to default), now it does nothing Reviewed-by: Brian Behlendorf <[email protected]> Signed-off-by: Ahelenia Ziemiańska <[email protected]> Closes openzfs#11878 Closes openzfs#11879
1 parent a8662d0 commit f30e0ef

File tree

1 file changed

+17
-76
lines changed

1 file changed

+17
-76
lines changed

module/os/linux/spl/spl-proc.c

Lines changed: 17 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -53,60 +53,6 @@ static struct proc_dir_entry *proc_spl_taskq_all = NULL;
5353
static struct proc_dir_entry *proc_spl_taskq = NULL;
5454
struct proc_dir_entry *proc_spl_kstat = NULL;
5555

56-
static int
57-
proc_copyin_string(char *kbuffer, int kbuffer_size, const char *ubuffer,
58-
int ubuffer_size)
59-
{
60-
int size;
61-
62-
if (ubuffer_size > kbuffer_size)
63-
return (-EOVERFLOW);
64-
65-
if (copy_from_user((void *)kbuffer, (void *)ubuffer, ubuffer_size))
66-
return (-EFAULT);
67-
68-
/* strip trailing whitespace */
69-
size = strnlen(kbuffer, ubuffer_size);
70-
while (size-- >= 0)
71-
if (!isspace(kbuffer[size]))
72-
break;
73-
74-
/* empty string */
75-
if (size < 0)
76-
return (-EINVAL);
77-
78-
/* no space to terminate */
79-
if (size == kbuffer_size)
80-
return (-EOVERFLOW);
81-
82-
kbuffer[size + 1] = 0;
83-
return (0);
84-
}
85-
86-
static int
87-
proc_copyout_string(char *ubuffer, int ubuffer_size, const char *kbuffer,
88-
char *append)
89-
{
90-
/*
91-
* NB if 'append' != NULL, it's a single character to append to the
92-
* copied out string - usually "\n", for /proc entries and
93-
* (i.e. a terminating zero byte) for sysctl entries
94-
*/
95-
int size = MIN(strlen(kbuffer), ubuffer_size);
96-
97-
if (copy_to_user(ubuffer, kbuffer, size))
98-
return (-EFAULT);
99-
100-
if (append != NULL && size < ubuffer_size) {
101-
if (copy_to_user(ubuffer + size, append, 1))
102-
return (-EFAULT);
103-
104-
size++;
105-
}
106-
107-
return (size);
108-
}
109-
11056
#ifdef DEBUG_KMEM
11157
static int
11258
proc_domemused(struct ctl_table *table, int write,
@@ -187,39 +133,34 @@ static int
187133
proc_dohostid(struct ctl_table *table, int write,
188134
void __user *buffer, size_t *lenp, loff_t *ppos)
189135
{
190-
int len, rc = 0;
191136
char *end, str[32];
137+
unsigned long hid;
138+
spl_ctl_table dummy = *table;
139+
140+
dummy.data = str;
141+
dummy.maxlen = sizeof (str) - 1;
142+
143+
if (!write)
144+
snprintf(str, sizeof (str), "%lx",
145+
(unsigned long) zone_get_hostid(NULL));
146+
147+
/* always returns 0 */
148+
proc_dostring(&dummy, write, buffer, lenp, ppos);
192149

193150
if (write) {
194151
/*
195152
* We can't use proc_doulongvec_minmax() in the write
196-
* case here because hostid while a hex value has no
197-
* leading 0x which confuses the helper function.
153+
* case here because hostid, while a hex value, has no
154+
* leading 0x, which confuses the helper function.
198155
*/
199-
rc = proc_copyin_string(str, sizeof (str), buffer, *lenp);
200-
if (rc < 0)
201-
return (rc);
202156

203-
spl_hostid = simple_strtoul(str, &end, 16);
157+
hid = simple_strtoul(str, &end, 16);
204158
if (str == end)
205159
return (-EINVAL);
206-
207-
} else {
208-
len = snprintf(str, sizeof (str), "%lx",
209-
(unsigned long) zone_get_hostid(NULL));
210-
if (*ppos >= len)
211-
rc = 0;
212-
else
213-
rc = proc_copyout_string(buffer,
214-
*lenp, str + *ppos, "\n");
215-
216-
if (rc >= 0) {
217-
*lenp = rc;
218-
*ppos += rc;
219-
}
160+
spl_hostid = hid;
220161
}
221162

222-
return (rc);
163+
return (0);
223164
}
224165

225166
static void

0 commit comments

Comments
 (0)