Rework the previous fix for the IB vs Ethernet sysctl handler to be more
generic and apply to all sysfs attributes: - Use sysctl_handle_string() instead of reimplementing it. - Remove trailing newline from the current value before passing it to userland and append a newline to the new string value before passing it to the attribute's store function. - Don't leak the temporary buffer if the first error check triggers. - Revert earlier change to mlx4 port mode handler. PR: kern/174213 Submitted by: Garrett Cooper Reviewed by: Shakar Klein @ Mellanox MFC after: 1 week
This commit is contained in:
parent
e32234295d
commit
c232b2aebb
@ -476,11 +476,11 @@ static ssize_t set_port_type(struct device *dev,
|
||||
int i;
|
||||
int err = 0;
|
||||
|
||||
if (!strcmp(buf, "ib"))
|
||||
if (!strcmp(buf, "ib\n"))
|
||||
info->tmp_type = MLX4_PORT_TYPE_IB;
|
||||
else if (!strcmp(buf, "eth"))
|
||||
else if (!strcmp(buf, "eth\n"))
|
||||
info->tmp_type = MLX4_PORT_TYPE_ETH;
|
||||
else if (!strcmp(buf, "auto"))
|
||||
else if (!strcmp(buf, "auto\n"))
|
||||
info->tmp_type = MLX4_PORT_TYPE_AUTO;
|
||||
else {
|
||||
mlx4_err(mdev, "%s is not supported port type\n", buf);
|
||||
|
@ -75,43 +75,41 @@ sysctl_handle_attr(SYSCTL_HANDLER_ARGS)
|
||||
struct kobject *kobj;
|
||||
struct attribute *attr;
|
||||
const struct sysfs_ops *ops;
|
||||
void *buf;
|
||||
char *buf;
|
||||
int error;
|
||||
ssize_t len;
|
||||
|
||||
kobj = arg1;
|
||||
attr = (struct attribute *)arg2;
|
||||
buf = (void *)get_zeroed_page(GFP_KERNEL);
|
||||
len = 1; /* Copy out a NULL byte at least. */
|
||||
if (kobj->ktype == NULL || kobj->ktype->sysfs_ops == NULL)
|
||||
return (ENODEV);
|
||||
ops = kobj->ktype->sysfs_ops;
|
||||
buf = (char *)get_zeroed_page(GFP_KERNEL);
|
||||
if (buf == NULL)
|
||||
return (ENOMEM);
|
||||
ops = kobj->ktype->sysfs_ops;
|
||||
if (ops->show) {
|
||||
len = ops->show(kobj, attr, buf);
|
||||
/*
|
||||
* It's valid not to have a 'show' so we just return 1 byte
|
||||
* of NULL.
|
||||
* It's valid to not have a 'show' so just return an
|
||||
* empty string.
|
||||
*/
|
||||
if (len < 0) {
|
||||
error = -len;
|
||||
len = 1;
|
||||
if (error != EIO)
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Trim trailing newline. */
|
||||
len--;
|
||||
buf[len] = '\0';
|
||||
}
|
||||
error = SYSCTL_OUT(req, buf, len);
|
||||
if (error || !req->newptr || ops->store == NULL)
|
||||
|
||||
/* Leave one trailing byte to append a newline. */
|
||||
error = sysctl_handle_string(oidp, buf, PAGE_SIZE - 1, req);
|
||||
if (error != 0 || req->newptr == NULL || ops->store == NULL)
|
||||
goto out;
|
||||
len = req->newlen - req->newidx;
|
||||
if (len >= PAGE_SIZE)
|
||||
error = EINVAL;
|
||||
else
|
||||
error = SYSCTL_IN(req, buf, len);
|
||||
if (error)
|
||||
goto out;
|
||||
((char *)buf)[len] = '\0';
|
||||
len = strlcat(buf, "\n", PAGE_SIZE);
|
||||
KASSERT(len < PAGE_SIZE, ("new attribute truncated"));
|
||||
len = ops->store(kobj, attr, buf, len);
|
||||
if (len < 0)
|
||||
error = -len;
|
||||
|
Loading…
Reference in New Issue
Block a user