mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 02:30:34 +02:00 
			
		
		
		
	ipc: add sysctl to specify desired next object id
Add 3 new variables and sysctls to tune them (by one "next_id" variable for messages, semaphores and shared memory respectively). This variable can be used to set desired id for next allocated IPC object. By default it's equal to -1 and old behaviour is preserved. If this variable is non-negative, then desired idr will be extracted from it and used as a start value to search for free IDR slot. Notes: 1) this patch doesn't guarantee that the new object will have desired id. So it's up to user space how to handle new object with wrong id. 2) After a sucessful id allocation attempt, "next_id" will be set back to -1 (if it was non-negative). [akpm@linux-foundation.org: checkpatch fixes] Signed-off-by: Stanislav Kinsbursky <skinsbursky@parallels.com> Cc: Serge Hallyn <serge.hallyn@canonical.com> Cc: "Eric W. Biederman" <ebiederm@xmission.com> Cc: Pavel Emelyanov <xemul@parallels.com> Cc: Al Viro <viro@zeniv.linux.org.uk> Cc: KOSAKI Motohiro <kosaki.motohiro@jp.fujitsu.com> Cc: Michael Kerrisk <mtk.manpages@gmail.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
		
							parent
							
								
									9afdacda02
								
							
						
					
					
						commit
						03f5956680
					
				
					 5 changed files with 65 additions and 4 deletions
				
			
		| 
						 | 
					@ -38,6 +38,7 @@ show up in /proc/sys/kernel:
 | 
				
			||||||
- l2cr                        [ PPC only ]
 | 
					- l2cr                        [ PPC only ]
 | 
				
			||||||
- modprobe                    ==> Documentation/debugging-modules.txt
 | 
					- modprobe                    ==> Documentation/debugging-modules.txt
 | 
				
			||||||
- modules_disabled
 | 
					- modules_disabled
 | 
				
			||||||
 | 
					- msg_next_id		      [ sysv ipc ]
 | 
				
			||||||
- msgmax
 | 
					- msgmax
 | 
				
			||||||
- msgmnb
 | 
					- msgmnb
 | 
				
			||||||
- msgmni
 | 
					- msgmni
 | 
				
			||||||
| 
						 | 
					@ -62,7 +63,9 @@ show up in /proc/sys/kernel:
 | 
				
			||||||
- rtsig-max
 | 
					- rtsig-max
 | 
				
			||||||
- rtsig-nr
 | 
					- rtsig-nr
 | 
				
			||||||
- sem
 | 
					- sem
 | 
				
			||||||
 | 
					- sem_next_id		      [ sysv ipc ]
 | 
				
			||||||
- sg-big-buff                 [ generic SCSI device (sg) ]
 | 
					- sg-big-buff                 [ generic SCSI device (sg) ]
 | 
				
			||||||
 | 
					- shm_next_id		      [ sysv ipc ]
 | 
				
			||||||
- shm_rmid_forced
 | 
					- shm_rmid_forced
 | 
				
			||||||
- shmall
 | 
					- shmall
 | 
				
			||||||
- shmmax                      [ sysv ipc ]
 | 
					- shmmax                      [ sysv ipc ]
 | 
				
			||||||
| 
						 | 
					@ -320,6 +323,22 @@ to false.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
==============================================================
 | 
					==============================================================
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					msg_next_id, sem_next_id, and shm_next_id:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					These three toggles allows to specify desired id for next allocated IPC
 | 
				
			||||||
 | 
					object: message, semaphore or shared memory respectively.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					By default they are equal to -1, which means generic allocation logic.
 | 
				
			||||||
 | 
					Possible values to set are in range {0..INT_MAX}.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Notes:
 | 
				
			||||||
 | 
					1) kernel doesn't guarantee, that new object will have desired id. So,
 | 
				
			||||||
 | 
					it's up to userspace, how to handle an object with "wrong" id.
 | 
				
			||||||
 | 
					2) Toggle with non-default value will be set back to -1 by kernel after
 | 
				
			||||||
 | 
					successful IPC object allocation.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					==============================================================
 | 
				
			||||||
 | 
					
 | 
				
			||||||
nmi_watchdog:
 | 
					nmi_watchdog:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Enables/Disables the NMI watchdog on x86 systems. When the value is
 | 
					Enables/Disables the NMI watchdog on x86 systems. When the value is
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -24,6 +24,7 @@ struct ipc_ids {
 | 
				
			||||||
	unsigned short seq_max;
 | 
						unsigned short seq_max;
 | 
				
			||||||
	struct rw_semaphore rw_mutex;
 | 
						struct rw_semaphore rw_mutex;
 | 
				
			||||||
	struct idr ipcs_idr;
 | 
						struct idr ipcs_idr;
 | 
				
			||||||
 | 
						int next_id;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct ipc_namespace {
 | 
					struct ipc_namespace {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -158,6 +158,9 @@ static int proc_ipcauto_dointvec_minmax(ctl_table *table, int write,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int zero;
 | 
					static int zero;
 | 
				
			||||||
static int one = 1;
 | 
					static int one = 1;
 | 
				
			||||||
 | 
					#ifdef CONFIG_CHECKPOINT_RESTORE
 | 
				
			||||||
 | 
					static int int_max = INT_MAX;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static struct ctl_table ipc_kern_table[] = {
 | 
					static struct ctl_table ipc_kern_table[] = {
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
| 
						 | 
					@ -227,6 +230,35 @@ static struct ctl_table ipc_kern_table[] = {
 | 
				
			||||||
		.extra1		= &zero,
 | 
							.extra1		= &zero,
 | 
				
			||||||
		.extra2		= &one,
 | 
							.extra2		= &one,
 | 
				
			||||||
	},
 | 
						},
 | 
				
			||||||
 | 
					#ifdef CONFIG_CHECKPOINT_RESTORE
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							.procname	= "sem_next_id",
 | 
				
			||||||
 | 
							.data		= &init_ipc_ns.ids[IPC_SEM_IDS].next_id,
 | 
				
			||||||
 | 
							.maxlen		= sizeof(init_ipc_ns.ids[IPC_SEM_IDS].next_id),
 | 
				
			||||||
 | 
							.mode		= 0644,
 | 
				
			||||||
 | 
							.proc_handler	= proc_ipc_dointvec_minmax,
 | 
				
			||||||
 | 
							.extra1		= &zero,
 | 
				
			||||||
 | 
							.extra2		= &int_max,
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							.procname	= "msg_next_id",
 | 
				
			||||||
 | 
							.data		= &init_ipc_ns.ids[IPC_MSG_IDS].next_id,
 | 
				
			||||||
 | 
							.maxlen		= sizeof(init_ipc_ns.ids[IPC_MSG_IDS].next_id),
 | 
				
			||||||
 | 
							.mode		= 0644,
 | 
				
			||||||
 | 
							.proc_handler	= proc_ipc_dointvec_minmax,
 | 
				
			||||||
 | 
							.extra1		= &zero,
 | 
				
			||||||
 | 
							.extra2		= &int_max,
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							.procname	= "shm_next_id",
 | 
				
			||||||
 | 
							.data		= &init_ipc_ns.ids[IPC_SHM_IDS].next_id,
 | 
				
			||||||
 | 
							.maxlen		= sizeof(init_ipc_ns.ids[IPC_SHM_IDS].next_id),
 | 
				
			||||||
 | 
							.mode		= 0644,
 | 
				
			||||||
 | 
							.proc_handler	= proc_ipc_dointvec_minmax,
 | 
				
			||||||
 | 
							.extra1		= &zero,
 | 
				
			||||||
 | 
							.extra2		= &int_max,
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
	{}
 | 
						{}
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										12
									
								
								ipc/util.c
									
									
									
									
									
								
							
							
						
						
									
										12
									
								
								ipc/util.c
									
									
									
									
									
								
							| 
						 | 
					@ -122,6 +122,7 @@ void ipc_init_ids(struct ipc_ids *ids)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ids->in_use = 0;
 | 
						ids->in_use = 0;
 | 
				
			||||||
	ids->seq = 0;
 | 
						ids->seq = 0;
 | 
				
			||||||
 | 
						ids->next_id = -1;
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		int seq_limit = INT_MAX/SEQ_MULTIPLIER;
 | 
							int seq_limit = INT_MAX/SEQ_MULTIPLIER;
 | 
				
			||||||
		if (seq_limit > USHRT_MAX)
 | 
							if (seq_limit > USHRT_MAX)
 | 
				
			||||||
| 
						 | 
					@ -252,6 +253,7 @@ int ipc_addid(struct ipc_ids* ids, struct kern_ipc_perm* new, int size)
 | 
				
			||||||
	kuid_t euid;
 | 
						kuid_t euid;
 | 
				
			||||||
	kgid_t egid;
 | 
						kgid_t egid;
 | 
				
			||||||
	int id, err;
 | 
						int id, err;
 | 
				
			||||||
 | 
						int next_id = ids->next_id;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (size > IPCMNI)
 | 
						if (size > IPCMNI)
 | 
				
			||||||
		size = IPCMNI;
 | 
							size = IPCMNI;
 | 
				
			||||||
| 
						 | 
					@ -264,7 +266,8 @@ int ipc_addid(struct ipc_ids* ids, struct kern_ipc_perm* new, int size)
 | 
				
			||||||
	rcu_read_lock();
 | 
						rcu_read_lock();
 | 
				
			||||||
	spin_lock(&new->lock);
 | 
						spin_lock(&new->lock);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	err = idr_get_new(&ids->ipcs_idr, new, &id);
 | 
						err = idr_get_new_above(&ids->ipcs_idr, new,
 | 
				
			||||||
 | 
									(next_id < 0) ? 0 : ipcid_to_idx(next_id), &id);
 | 
				
			||||||
	if (err) {
 | 
						if (err) {
 | 
				
			||||||
		spin_unlock(&new->lock);
 | 
							spin_unlock(&new->lock);
 | 
				
			||||||
		rcu_read_unlock();
 | 
							rcu_read_unlock();
 | 
				
			||||||
| 
						 | 
					@ -277,9 +280,14 @@ int ipc_addid(struct ipc_ids* ids, struct kern_ipc_perm* new, int size)
 | 
				
			||||||
	new->cuid = new->uid = euid;
 | 
						new->cuid = new->uid = euid;
 | 
				
			||||||
	new->gid = new->cgid = egid;
 | 
						new->gid = new->cgid = egid;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (next_id < 0) {
 | 
				
			||||||
		new->seq = ids->seq++;
 | 
							new->seq = ids->seq++;
 | 
				
			||||||
	if(ids->seq > ids->seq_max)
 | 
							if (ids->seq > ids->seq_max)
 | 
				
			||||||
			ids->seq = 0;
 | 
								ids->seq = 0;
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							new->seq = ipcid_to_seqx(next_id);
 | 
				
			||||||
 | 
							ids->next_id = -1;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	new->id = ipc_buildid(id, new->seq);
 | 
						new->id = ipc_buildid(id, new->seq);
 | 
				
			||||||
	return id;
 | 
						return id;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -92,6 +92,7 @@ void __init ipc_init_proc_interface(const char *path, const char *header,
 | 
				
			||||||
#define IPC_SHM_IDS	2
 | 
					#define IPC_SHM_IDS	2
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define ipcid_to_idx(id) ((id) % SEQ_MULTIPLIER)
 | 
					#define ipcid_to_idx(id) ((id) % SEQ_MULTIPLIER)
 | 
				
			||||||
 | 
					#define ipcid_to_seqx(id) ((id) / SEQ_MULTIPLIER)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* must be called with ids->rw_mutex acquired for writing */
 | 
					/* must be called with ids->rw_mutex acquired for writing */
 | 
				
			||||||
int ipc_addid(struct ipc_ids *, struct kern_ipc_perm *, int);
 | 
					int ipc_addid(struct ipc_ids *, struct kern_ipc_perm *, int);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue