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:
John Baldwin 2013-07-18 14:06:01 +00:00
parent e32234295d
commit c232b2aebb
2 changed files with 18 additions and 20 deletions

View File

@ -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);

View File

@ -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;