Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/ipc/ipc_sysctl.c
10817 views
1
/*
2
* Copyright (C) 2007
3
*
4
* Author: Eric Biederman <[email protected]>
5
*
6
* This program is free software; you can redistribute it and/or
7
* modify it under the terms of the GNU General Public License as
8
* published by the Free Software Foundation, version 2 of the
9
* License.
10
*/
11
12
#include <linux/module.h>
13
#include <linux/ipc.h>
14
#include <linux/nsproxy.h>
15
#include <linux/sysctl.h>
16
#include <linux/uaccess.h>
17
#include <linux/ipc_namespace.h>
18
#include <linux/msg.h>
19
#include "util.h"
20
21
static void *get_ipc(ctl_table *table)
22
{
23
char *which = table->data;
24
struct ipc_namespace *ipc_ns = current->nsproxy->ipc_ns;
25
which = (which - (char *)&init_ipc_ns) + (char *)ipc_ns;
26
return which;
27
}
28
29
#ifdef CONFIG_PROC_SYSCTL
30
static int proc_ipc_dointvec(ctl_table *table, int write,
31
void __user *buffer, size_t *lenp, loff_t *ppos)
32
{
33
struct ctl_table ipc_table;
34
memcpy(&ipc_table, table, sizeof(ipc_table));
35
ipc_table.data = get_ipc(table);
36
37
return proc_dointvec(&ipc_table, write, buffer, lenp, ppos);
38
}
39
40
static int proc_ipc_callback_dointvec(ctl_table *table, int write,
41
void __user *buffer, size_t *lenp, loff_t *ppos)
42
{
43
struct ctl_table ipc_table;
44
size_t lenp_bef = *lenp;
45
int rc;
46
47
memcpy(&ipc_table, table, sizeof(ipc_table));
48
ipc_table.data = get_ipc(table);
49
50
rc = proc_dointvec(&ipc_table, write, buffer, lenp, ppos);
51
52
if (write && !rc && lenp_bef == *lenp)
53
/*
54
* Tunable has successfully been changed by hand. Disable its
55
* automatic adjustment. This simply requires unregistering
56
* the notifiers that trigger recalculation.
57
*/
58
unregister_ipcns_notifier(current->nsproxy->ipc_ns);
59
60
return rc;
61
}
62
63
static int proc_ipc_doulongvec_minmax(ctl_table *table, int write,
64
void __user *buffer, size_t *lenp, loff_t *ppos)
65
{
66
struct ctl_table ipc_table;
67
memcpy(&ipc_table, table, sizeof(ipc_table));
68
ipc_table.data = get_ipc(table);
69
70
return proc_doulongvec_minmax(&ipc_table, write, buffer,
71
lenp, ppos);
72
}
73
74
/*
75
* Routine that is called when the file "auto_msgmni" has successfully been
76
* written.
77
* Two values are allowed:
78
* 0: unregister msgmni's callback routine from the ipc namespace notifier
79
* chain. This means that msgmni won't be recomputed anymore upon memory
80
* add/remove or ipc namespace creation/removal.
81
* 1: register back the callback routine.
82
*/
83
static void ipc_auto_callback(int val)
84
{
85
if (!val)
86
unregister_ipcns_notifier(current->nsproxy->ipc_ns);
87
else {
88
/*
89
* Re-enable automatic recomputing only if not already
90
* enabled.
91
*/
92
recompute_msgmni(current->nsproxy->ipc_ns);
93
cond_register_ipcns_notifier(current->nsproxy->ipc_ns);
94
}
95
}
96
97
static int proc_ipcauto_dointvec_minmax(ctl_table *table, int write,
98
void __user *buffer, size_t *lenp, loff_t *ppos)
99
{
100
struct ctl_table ipc_table;
101
size_t lenp_bef = *lenp;
102
int oldval;
103
int rc;
104
105
memcpy(&ipc_table, table, sizeof(ipc_table));
106
ipc_table.data = get_ipc(table);
107
oldval = *((int *)(ipc_table.data));
108
109
rc = proc_dointvec_minmax(&ipc_table, write, buffer, lenp, ppos);
110
111
if (write && !rc && lenp_bef == *lenp) {
112
int newval = *((int *)(ipc_table.data));
113
/*
114
* The file "auto_msgmni" has correctly been set.
115
* React by (un)registering the corresponding tunable, if the
116
* value has changed.
117
*/
118
if (newval != oldval)
119
ipc_auto_callback(newval);
120
}
121
122
return rc;
123
}
124
125
#else
126
#define proc_ipc_doulongvec_minmax NULL
127
#define proc_ipc_dointvec NULL
128
#define proc_ipc_callback_dointvec NULL
129
#define proc_ipcauto_dointvec_minmax NULL
130
#endif
131
132
static int zero;
133
static int one = 1;
134
135
static struct ctl_table ipc_kern_table[] = {
136
{
137
.procname = "shmmax",
138
.data = &init_ipc_ns.shm_ctlmax,
139
.maxlen = sizeof (init_ipc_ns.shm_ctlmax),
140
.mode = 0644,
141
.proc_handler = proc_ipc_doulongvec_minmax,
142
},
143
{
144
.procname = "shmall",
145
.data = &init_ipc_ns.shm_ctlall,
146
.maxlen = sizeof (init_ipc_ns.shm_ctlall),
147
.mode = 0644,
148
.proc_handler = proc_ipc_doulongvec_minmax,
149
},
150
{
151
.procname = "shmmni",
152
.data = &init_ipc_ns.shm_ctlmni,
153
.maxlen = sizeof (init_ipc_ns.shm_ctlmni),
154
.mode = 0644,
155
.proc_handler = proc_ipc_dointvec,
156
},
157
{
158
.procname = "msgmax",
159
.data = &init_ipc_ns.msg_ctlmax,
160
.maxlen = sizeof (init_ipc_ns.msg_ctlmax),
161
.mode = 0644,
162
.proc_handler = proc_ipc_dointvec,
163
},
164
{
165
.procname = "msgmni",
166
.data = &init_ipc_ns.msg_ctlmni,
167
.maxlen = sizeof (init_ipc_ns.msg_ctlmni),
168
.mode = 0644,
169
.proc_handler = proc_ipc_callback_dointvec,
170
},
171
{
172
.procname = "msgmnb",
173
.data = &init_ipc_ns.msg_ctlmnb,
174
.maxlen = sizeof (init_ipc_ns.msg_ctlmnb),
175
.mode = 0644,
176
.proc_handler = proc_ipc_dointvec,
177
},
178
{
179
.procname = "sem",
180
.data = &init_ipc_ns.sem_ctls,
181
.maxlen = 4*sizeof (int),
182
.mode = 0644,
183
.proc_handler = proc_ipc_dointvec,
184
},
185
{
186
.procname = "auto_msgmni",
187
.data = &init_ipc_ns.auto_msgmni,
188
.maxlen = sizeof(int),
189
.mode = 0644,
190
.proc_handler = proc_ipcauto_dointvec_minmax,
191
.extra1 = &zero,
192
.extra2 = &one,
193
},
194
{}
195
};
196
197
static struct ctl_table ipc_root_table[] = {
198
{
199
.procname = "kernel",
200
.mode = 0555,
201
.child = ipc_kern_table,
202
},
203
{}
204
};
205
206
static int __init ipc_sysctl_init(void)
207
{
208
register_sysctl_table(ipc_root_table);
209
return 0;
210
}
211
212
__initcall(ipc_sysctl_init);
213
214