Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 49a0c458 authored by Eric W. Biederman's avatar Eric W. Biederman Committed by Linus Torvalds
Browse files

sysctl: Factor out sysctl_data.



There as been no easy way to wrap the default sysctl strategy routine except
for returning 0.  Which is not always what we want.  The few instances I have
seen that want different behaviour have written their own version of
sysctl_data.  While not too hard it is unnecessary code and has the potential
for extra bugs.

So to make these situations easier and make that part of sysctl more symetric
I have factord sysctl_data out of do_sysctl_strategy and exported as a
function everyone can use.

Further having sysctl_data be an explicit function makes checking for badly
formed sysctl tables much easier.

Signed-off-by: default avatarEric W. Biederman <ebiederm@xmission.com>
Cc: Alexey Dobriyan <adobriyan@sw.ru>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent d8217f07
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -972,6 +972,7 @@ extern int do_sysctl_strategy (struct ctl_table *table,
			       void __user *oldval, size_t __user *oldlenp,
			       void __user *newval, size_t newlen);

extern ctl_handler sysctl_data;
extern ctl_handler sysctl_string;
extern ctl_handler sysctl_intvec;
extern ctl_handler sysctl_jiffies;
+46 −20
Original line number Diff line number Diff line
@@ -1443,7 +1443,6 @@ int do_sysctl_strategy (struct ctl_table *table,
			void __user *newval, size_t newlen)
{
	int op = 0, rc;
	size_t len;

	if (oldval)
		op |= 004;
@@ -1464,25 +1463,10 @@ int do_sysctl_strategy (struct ctl_table *table,
	/* If there is no strategy routine, or if the strategy returns
	 * zero, proceed with automatic r/w */
	if (table->data && table->maxlen) {
		if (oldval && oldlenp) {
			if (get_user(len, oldlenp))
				return -EFAULT;
			if (len) {
				if (len > table->maxlen)
					len = table->maxlen;
				if(copy_to_user(oldval, table->data, len))
					return -EFAULT;
				if(put_user(len, oldlenp))
					return -EFAULT;
			}
		}
		if (newval && newlen) {
			len = newlen;
			if (len > table->maxlen)
				len = table->maxlen;
			if(copy_from_user(table->data, newval, len))
				return -EFAULT;
		}
		rc = sysctl_data(table, name, nlen, oldval, oldlenp,
				 newval, newlen);
		if (rc < 0)
			return rc;
	}
	return 0;
}
@@ -2381,6 +2365,40 @@ int proc_doulongvec_ms_jiffies_minmax(struct ctl_table *table, int write,
 * General sysctl support routines 
 */

/* The generic sysctl data routine (used if no strategy routine supplied) */
int sysctl_data(struct ctl_table *table, int __user *name, int nlen,
		void __user *oldval, size_t __user *oldlenp,
		void __user *newval, size_t newlen)
{
	size_t len;

	/* Get out of I don't have a variable */
	if (!table->data || !table->maxlen)
		return -ENOTDIR;

	if (oldval && oldlenp) {
		if (get_user(len, oldlenp))
			return -EFAULT;
		if (len) {
			if (len > table->maxlen)
				len = table->maxlen;
			if (copy_to_user(oldval, table->data, len))
				return -EFAULT;
			if (put_user(len, oldlenp))
				return -EFAULT;
		}
	}

	if (newval && newlen) {
		if (newlen > table->maxlen)
			newlen = table->maxlen;

		if (copy_from_user(table->data, newval, newlen))
			return -EFAULT;
	}
	return 1;
}

/* The generic string strategy routine: */
int sysctl_string(struct ctl_table *table, int __user *name, int nlen,
		  void __user *oldval, size_t __user *oldlenp,
@@ -2569,6 +2587,13 @@ out:
	return -ENOSYS;
}

int sysctl_data(struct ctl_table *table, int __user *name, int nlen,
		  void __user *oldval, size_t __user *oldlenp,
		  void __user *newval, size_t newlen)
{
	return -ENOSYS;
}

int sysctl_string(struct ctl_table *table, int __user *name, int nlen,
		  void __user *oldval, size_t __user *oldlenp,
		  void __user *newval, size_t newlen)
@@ -2616,4 +2641,5 @@ EXPORT_SYMBOL(sysctl_intvec);
EXPORT_SYMBOL(sysctl_jiffies);
EXPORT_SYMBOL(sysctl_ms_jiffies);
EXPORT_SYMBOL(sysctl_string);
EXPORT_SYMBOL(sysctl_data);
EXPORT_SYMBOL(unregister_sysctl_table);