2519 lines · 56.8 KB · C
RawDownload
		.proc_handler	= proc_dointvec_minmax,		.extra1		= &zero,		.extra2		= &two,	},#if defined(CONFIG_BINFMT_MISC) || defined(CONFIG_BINFMT_MISC_MODULE)	{		.procname	= "binfmt_misc",		.mode		= 0555,		.child		= binfmt_misc_table,	},#endif	{		.procname	= "pipe-max-size",		.data		= &pipe_max_size,		.maxlen		= sizeof(int),		.mode		= 0644,		.proc_handler	= &pipe_proc_fn,		.extra1		= &pipe_min_size,	},	{ }}; static struct ctl_table debug_table[] = {#if defined(CONFIG_X86) || defined(CONFIG_PPC) || defined(CONFIG_SPARC) || \    defined(CONFIG_S390) || defined(CONFIG_TILE)	{		.procname	= "exception-trace",		.data		= &show_unhandled_signals,		.maxlen		= sizeof(int),		.mode		= 0644,		.proc_handler	= proc_dointvec	},#endif#if defined(CONFIG_OPTPROBES)	{		.procname	= "kprobes-optimization",		.data		= &sysctl_kprobes_optimization,		.maxlen		= sizeof(int),		.mode		= 0644,		.proc_handler	= proc_kprobes_optimization_handler,		.extra1		= &zero,		.extra2		= &one,	},#endif	{ }}; static struct ctl_table dev_table[] = {	{ }}; int __init sysctl_init(void){	register_sysctl_table(sysctl_base_table);	return 0;} #endif /* CONFIG_SYSCTL */ /* * /proc/sys support */ #ifdef CONFIG_PROC_SYSCTL static int _proc_do_string(void* data, int maxlen, int write,			   void __user *buffer,			   size_t *lenp, loff_t *ppos){	size_t len;	char __user *p;	char c; 	if (!data || !maxlen || !*lenp) {		*lenp = 0;		return 0;	} 	if (write) {		len = 0;		p = buffer;		while (len < *lenp) {			if (get_user(c, p++))				return -EFAULT;			if (c == 0 || c == '\n')				break;			len++;		}		if (len >= maxlen)			len = maxlen-1;		if(copy_from_user(data, buffer, len))			return -EFAULT;		((char *) data)[len] = 0;		*ppos += *lenp;	} else {		len = strlen(data);		if (len > maxlen)			len = maxlen; 		if (*ppos > len) {			*lenp = 0;			return 0;		} 		data += *ppos;		len  -= *ppos; 		if (len > *lenp)			len = *lenp;		if (len)			if(copy_to_user(buffer, data, len))				return -EFAULT;		if (len < *lenp) {			if(put_user('\n', ((char __user *) buffer) + len))				return -EFAULT;			len++;		}		*lenp = len;		*ppos += len;	}	return 0;} /** * proc_dostring - read a string sysctl * @table: the sysctl table * @write: %TRUE if this is a write to the sysctl file * @buffer: the user buffer * @lenp: the size of the user buffer * @ppos: file position * * Reads/writes a string from/to the user buffer. If the kernel * buffer provided is not large enough to hold the string, the * string is truncated. The copied string is %NULL-terminated. * If the string is being read by the user process, it is copied * and a newline '\n' is added. It is truncated if the buffer is * not large enough. * * Returns 0 on success. */int proc_dostring(struct ctl_table *table, int write,		  void __user *buffer, size_t *lenp, loff_t *ppos){	return _proc_do_string(table->data, table->maxlen, write,			       buffer, lenp, ppos);} static size_t proc_skip_spaces(char **buf){	size_t ret;	char *tmp = skip_spaces(*buf);	ret = tmp - *buf;	*buf = tmp;	return ret;} static void proc_skip_char(char **buf, size_t *size, const char v){	while (*size) {		if (**buf != v)			break;		(*size)--;		(*buf)++;	}} #define TMPBUFLEN 22/** * proc_get_long - reads an ASCII formatted integer from a user buffer * * @buf: a kernel buffer * @size: size of the kernel buffer * @val: this is where the number will be stored * @neg: set to %TRUE if number is negative * @perm_tr: a vector which contains the allowed trailers * @perm_tr_len: size of the perm_tr vector * @tr: pointer to store the trailer character * * In case of success %0 is returned and @buf and @size are updated with * the amount of bytes read. If @tr is non-NULL and a trailing * character exists (size is non-zero after returning from this * function), @tr is updated with the trailing character. */static int proc_get_long(char **buf, size_t *size,			  unsigned long *val, bool *neg,			  const char *perm_tr, unsigned perm_tr_len, char *tr){	int len;	char *p, tmp[TMPBUFLEN]; 	if (!*size)		return -EINVAL; 	len = *size;	if (len > TMPBUFLEN - 1)		len = TMPBUFLEN - 1; 	memcpy(tmp, *buf, len); 	tmp[len] = 0;	p = tmp;	if (*p == '-' && *size > 1) {		*neg = true;		p++;	} else		*neg = false;	if (!isdigit(*p))		return -EINVAL; 	*val = simple_strtoul(p, &p, 0); 	len = p - tmp; 	/* We don't know if the next char is whitespace thus we may accept	 * invalid integers (e.g. 1234...a) or two integers instead of one	 * (e.g. 123...1). So lets not allow such large numbers. */	if (len == TMPBUFLEN - 1)		return -EINVAL; 	if (len < *size && perm_tr_len && !memchr(perm_tr, *p, perm_tr_len))		return -EINVAL; 	if (tr && (len < *size))		*tr = *p; 	*buf += len;	*size -= len; 	return 0;} /** * proc_put_long - converts an integer to a decimal ASCII formatted string * * @buf: the user buffer * @size: the size of the user buffer * @val: the integer to be converted * @neg: sign of the number, %TRUE for negative * * In case of success %0 is returned and @buf and @size are updated with * the amount of bytes written. */static int proc_put_long(void __user **buf, size_t *size, unsigned long val,			  bool neg){	int len;	char tmp[TMPBUFLEN], *p = tmp; 	sprintf(p, "%s%lu", neg ? "-" : "", val);	len = strlen(tmp);	if (len > *size)		len = *size;	if (copy_to_user(*buf, tmp, len))		return -EFAULT;	*size -= len;	*buf += len;	return 0;}#undef TMPBUFLEN static int proc_put_char(void __user **buf, size_t *size, char c){	if (*size) {		char __user **buffer = (char __user **)buf;		if (put_user(c, *buffer))			return -EFAULT;		(*size)--, (*buffer)++;		*buf = *buffer;	}	return 0;} static int do_proc_dointvec_conv(bool *negp, unsigned long *lvalp,				 int *valp,				 int write, void *data){	if (write) {		*valp = *negp ? -*lvalp : *lvalp;	} else {		int val = *valp;		if (val < 0) {			*negp = true;			*lvalp = (unsigned long)-val;		} else {			*negp = false;			*lvalp = (unsigned long)val;		}	}	return 0;} static const char proc_wspace_sep[] = { ' ', '\t', '\n' }; static int __do_proc_dointvec(void *tbl_data, struct ctl_table *table,		  int write, void __user *buffer,		  size_t *lenp, loff_t *ppos,		  int (*conv)(bool *negp, unsigned long *lvalp, int *valp,			      int write, void *data),		  void *data){	int *i, vleft, first = 1, err = 0;	unsigned long page = 0;	size_t left;	char *kbuf;		if (!tbl_data || !table->maxlen || !*lenp || (*ppos && !write)) {		*lenp = 0;		return 0;	}		i = (int *) tbl_data;	vleft = table->maxlen / sizeof(*i);	left = *lenp; 	if (!conv)		conv = do_proc_dointvec_conv; 	if (write) {		if (left > PAGE_SIZE - 1)			left = PAGE_SIZE - 1;		page = __get_free_page(GFP_TEMPORARY);		kbuf = (char *) page;		if (!kbuf)			return -ENOMEM;		if (copy_from_user(kbuf, buffer, left)) {			err = -EFAULT;			goto free;		}		kbuf[left] = 0;	} 	for (; left && vleft--; i++, first=0) {		unsigned long lval;		bool neg; 		if (write) {			left -= proc_skip_spaces(&kbuf); 			if (!left)				break;			err = proc_get_long(&kbuf, &left, &lval, &neg,					     proc_wspace_sep,					     sizeof(proc_wspace_sep), NULL);			if (err)				break;			if (conv(&neg, &lval, i, 1, data)) {				err = -EINVAL;				break;			}		} else {			if (conv(&neg, &lval, i, 0, data)) {				err = -EINVAL;				break;			}			if (!first)				err = proc_put_char(&buffer, &left, '\t');			if (err)				break;			err = proc_put_long(&buffer, &left, lval, neg);			if (err)				break;		}	} 	if (!write && !first && left && !err)		err = proc_put_char(&buffer, &left, '\n');	if (write && !err && left)		left -= proc_skip_spaces(&kbuf);free:	if (write) {		free_page(page);		if (first)			return err ? : -EINVAL;	}	*lenp -= left;	*ppos += *lenp;	return err;} static int do_proc_dointvec(struct ctl_table *table, int write,		  void __user *buffer, size_t *lenp, loff_t *ppos,		  int (*conv)(bool *negp, unsigned long *lvalp, int *valp,			      int write, void *data),		  void *data){	return __do_proc_dointvec(table->data, table, write,			buffer, lenp, ppos, conv, data);} /** * proc_dointvec - read a vector of integers * @table: the sysctl table * @write: %TRUE if this is a write to the sysctl file * @buffer: the user buffer * @lenp: the size of the user buffer * @ppos: file position * * Reads/writes up to table->maxlen/sizeof(unsigned int) integer * values from/to the user buffer, treated as an ASCII string.  * * Returns 0 on success. */int proc_dointvec(struct ctl_table *table, int write,		     void __user *buffer, size_t *lenp, loff_t *ppos){    return do_proc_dointvec(table,write,buffer,lenp,ppos,		    	    NULL,NULL);} /* * Taint values can only be increased * This means we can safely use a temporary. */static int proc_taint(struct ctl_table *table, int write,			       void __user *buffer, size_t *lenp, loff_t *ppos){	struct ctl_table t;	unsigned long tmptaint = get_taint();	int err; 	if (write && !capable(CAP_SYS_ADMIN))		return -EPERM; 	t = *table;	t.data = &tmptaint;	err = proc_doulongvec_minmax(&t, write, buffer, lenp, ppos);	if (err < 0)		return err; 	if (write) {		/*		 * Poor man's atomic or. Not worth adding a primitive		 * to everyone's atomic.h for this		 */		int i;		for (i = 0; i < BITS_PER_LONG && tmptaint >> i; i++) {			if ((tmptaint >> i) & 1)				add_taint(i);		}	} 	return err;} #ifdef CONFIG_PRINTKstatic int proc_dointvec_minmax_sysadmin(struct ctl_table *table, int write,				void __user *buffer, size_t *lenp, loff_t *ppos){	if (write && !capable(CAP_SYS_ADMIN))		return -EPERM; 	return proc_dointvec_minmax(table, write, buffer, lenp, ppos);}#endif struct do_proc_dointvec_minmax_conv_param {	int *min;	int *max;}; static int do_proc_dointvec_minmax_conv(bool *negp, unsigned long *lvalp,					int *valp,					int write, void *data){	struct do_proc_dointvec_minmax_conv_param *param = data;	if (write) {		int val = *negp ? -*lvalp : *lvalp;		if ((param->min && *param->min > val) ||		    (param->max && *param->max < val))			return -EINVAL;		*valp = val;	} else {		int val = *valp;		if (val < 0) {			*negp = true;			*lvalp = (unsigned long)-val;		} else {			*negp = false;			*lvalp = (unsigned long)val;		}	}	return 0;} /** * proc_dointvec_minmax - read a vector of integers with min/max values * @table: the sysctl table * @write: %TRUE if this is a write to the sysctl file * @buffer: the user buffer * @lenp: the size of the user buffer * @ppos: file position * * Reads/writes up to table->maxlen/sizeof(unsigned int) integer * values from/to the user buffer, treated as an ASCII string. * * This routine will ensure the values are within the range specified by * table->extra1 (min) and table->extra2 (max). * * Returns 0 on success. */

Lines 1501–2000 of 2519. Previous lines

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t