19
19
#include <linux/kmemleak.h>
20
20
#include "internal.h"
21
21
22
- #define list_for_each_table_entry (entry , table ) \
23
- for ((entry) = (table); (entry)->procname; (entry)++)
22
+ #define list_for_each_table_entry (entry , header ) \
23
+ entry = header->ctl_table; \
24
+ for (size_t i = 0 ; i < header->ctl_table_size && entry->procname; ++i, entry++)
24
25
25
26
static const struct dentry_operations proc_sys_dentry_operations ;
26
27
static const struct file_operations proc_sys_file_operations ;
@@ -43,7 +44,7 @@ static struct ctl_table sysctl_mount_point[] = {
43
44
*/
44
45
struct ctl_table_header * register_sysctl_mount_point (const char * path )
45
46
{
46
- return register_sysctl (path , sysctl_mount_point );
47
+ return register_sysctl_sz (path , sysctl_mount_point , 0 );
47
48
}
48
49
EXPORT_SYMBOL (register_sysctl_mount_point );
49
50
@@ -188,9 +189,10 @@ static void erase_entry(struct ctl_table_header *head, struct ctl_table *entry)
188
189
189
190
static void init_header (struct ctl_table_header * head ,
190
191
struct ctl_table_root * root , struct ctl_table_set * set ,
191
- struct ctl_node * node , struct ctl_table * table )
192
+ struct ctl_node * node , struct ctl_table * table , size_t table_size )
192
193
{
193
194
head -> ctl_table = table ;
195
+ head -> ctl_table_size = table_size ;
194
196
head -> ctl_table_arg = table ;
195
197
head -> used = 0 ;
196
198
head -> count = 1 ;
@@ -204,7 +206,7 @@ static void init_header(struct ctl_table_header *head,
204
206
if (node ) {
205
207
struct ctl_table * entry ;
206
208
207
- list_for_each_table_entry (entry , table ) {
209
+ list_for_each_table_entry (entry , head ) {
208
210
node -> header = head ;
209
211
node ++ ;
210
212
}
@@ -215,7 +217,7 @@ static void erase_header(struct ctl_table_header *head)
215
217
{
216
218
struct ctl_table * entry ;
217
219
218
- list_for_each_table_entry (entry , head -> ctl_table )
220
+ list_for_each_table_entry (entry , head )
219
221
erase_entry (head , entry );
220
222
}
221
223
@@ -242,7 +244,7 @@ static int insert_header(struct ctl_dir *dir, struct ctl_table_header *header)
242
244
err = insert_links (header );
243
245
if (err )
244
246
goto fail_links ;
245
- list_for_each_table_entry (entry , header -> ctl_table ) {
247
+ list_for_each_table_entry (entry , header ) {
246
248
err = insert_entry (header , entry );
247
249
if (err )
248
250
goto fail ;
@@ -973,7 +975,7 @@ static struct ctl_dir *new_dir(struct ctl_table_set *set,
973
975
memcpy (new_name , name , namelen );
974
976
table [0 ].procname = new_name ;
975
977
table [0 ].mode = S_IFDIR |S_IRUGO |S_IXUGO ;
976
- init_header (& new -> header , set -> dir .header .root , set , node , table );
978
+ init_header (& new -> header , set -> dir .header .root , set , node , table , 1 );
977
979
978
980
return new ;
979
981
}
@@ -1125,11 +1127,11 @@ static int sysctl_check_table_array(const char *path, struct ctl_table *table)
1125
1127
return err ;
1126
1128
}
1127
1129
1128
- static int sysctl_check_table (const char * path , struct ctl_table * table )
1130
+ static int sysctl_check_table (const char * path , struct ctl_table_header * header )
1129
1131
{
1130
1132
struct ctl_table * entry ;
1131
1133
int err = 0 ;
1132
- list_for_each_table_entry (entry , table ) {
1134
+ list_for_each_table_entry (entry , header ) {
1133
1135
if ((entry -> proc_handler == proc_dostring ) ||
1134
1136
(entry -> proc_handler == proc_dobool ) ||
1135
1137
(entry -> proc_handler == proc_dointvec ) ||
@@ -1159,8 +1161,7 @@ static int sysctl_check_table(const char *path, struct ctl_table *table)
1159
1161
return err ;
1160
1162
}
1161
1163
1162
- static struct ctl_table_header * new_links (struct ctl_dir * dir , struct ctl_table * table ,
1163
- struct ctl_table_root * link_root )
1164
+ static struct ctl_table_header * new_links (struct ctl_dir * dir , struct ctl_table_header * head )
1164
1165
{
1165
1166
struct ctl_table * link_table , * entry , * link ;
1166
1167
struct ctl_table_header * links ;
@@ -1170,7 +1171,7 @@ static struct ctl_table_header *new_links(struct ctl_dir *dir, struct ctl_table
1170
1171
1171
1172
name_bytes = 0 ;
1172
1173
nr_entries = 0 ;
1173
- list_for_each_table_entry (entry , table ) {
1174
+ list_for_each_table_entry (entry , head ) {
1174
1175
nr_entries ++ ;
1175
1176
name_bytes += strlen (entry -> procname ) + 1 ;
1176
1177
}
@@ -1189,31 +1190,33 @@ static struct ctl_table_header *new_links(struct ctl_dir *dir, struct ctl_table
1189
1190
link_name = (char * )& link_table [nr_entries + 1 ];
1190
1191
link = link_table ;
1191
1192
1192
- list_for_each_table_entry (entry , table ) {
1193
+ list_for_each_table_entry (entry , head ) {
1193
1194
int len = strlen (entry -> procname ) + 1 ;
1194
1195
memcpy (link_name , entry -> procname , len );
1195
1196
link -> procname = link_name ;
1196
1197
link -> mode = S_IFLNK |S_IRWXUGO ;
1197
- link -> data = link_root ;
1198
+ link -> data = head -> root ;
1198
1199
link_name += len ;
1199
1200
link ++ ;
1200
1201
}
1201
- init_header (links , dir -> header .root , dir -> header .set , node , link_table );
1202
+ init_header (links , dir -> header .root , dir -> header .set , node , link_table ,
1203
+ head -> ctl_table_size );
1202
1204
links -> nreg = nr_entries ;
1203
1205
1204
1206
return links ;
1205
1207
}
1206
1208
1207
1209
static bool get_links (struct ctl_dir * dir ,
1208
- struct ctl_table * table , struct ctl_table_root * link_root )
1210
+ struct ctl_table_header * header ,
1211
+ struct ctl_table_root * link_root )
1209
1212
{
1210
- struct ctl_table_header * head ;
1213
+ struct ctl_table_header * tmp_head ;
1211
1214
struct ctl_table * entry , * link ;
1212
1215
1213
1216
/* Are there links available for every entry in table? */
1214
- list_for_each_table_entry (entry , table ) {
1217
+ list_for_each_table_entry (entry , header ) {
1215
1218
const char * procname = entry -> procname ;
1216
- link = find_entry (& head , dir , procname , strlen (procname ));
1219
+ link = find_entry (& tmp_head , dir , procname , strlen (procname ));
1217
1220
if (!link )
1218
1221
return false;
1219
1222
if (S_ISDIR (link -> mode ) && S_ISDIR (entry -> mode ))
@@ -1224,10 +1227,10 @@ static bool get_links(struct ctl_dir *dir,
1224
1227
}
1225
1228
1226
1229
/* The checks passed. Increase the registration count on the links */
1227
- list_for_each_table_entry (entry , table ) {
1230
+ list_for_each_table_entry (entry , header ) {
1228
1231
const char * procname = entry -> procname ;
1229
- link = find_entry (& head , dir , procname , strlen (procname ));
1230
- head -> nreg ++ ;
1232
+ link = find_entry (& tmp_head , dir , procname , strlen (procname ));
1233
+ tmp_head -> nreg ++ ;
1231
1234
}
1232
1235
return true;
1233
1236
}
@@ -1246,21 +1249,21 @@ static int insert_links(struct ctl_table_header *head)
1246
1249
if (IS_ERR (core_parent ))
1247
1250
return 0 ;
1248
1251
1249
- if (get_links (core_parent , head -> ctl_table , head -> root ))
1252
+ if (get_links (core_parent , head , head -> root ))
1250
1253
return 0 ;
1251
1254
1252
1255
core_parent -> header .nreg ++ ;
1253
1256
spin_unlock (& sysctl_lock );
1254
1257
1255
- links = new_links (core_parent , head -> ctl_table , head -> root );
1258
+ links = new_links (core_parent , head );
1256
1259
1257
1260
spin_lock (& sysctl_lock );
1258
1261
err = - ENOMEM ;
1259
1262
if (!links )
1260
1263
goto out ;
1261
1264
1262
1265
err = 0 ;
1263
- if (get_links (core_parent , head -> ctl_table , head -> root )) {
1266
+ if (get_links (core_parent , head , head -> root )) {
1264
1267
kfree (links );
1265
1268
goto out ;
1266
1269
}
@@ -1310,6 +1313,7 @@ static struct ctl_dir *sysctl_mkdir_p(struct ctl_dir *dir, const char *path)
1310
1313
* should not be free'd after registration. So it should not be
1311
1314
* used on stack. It can either be a global or dynamically allocated
1312
1315
* by the caller and free'd later after sysctl unregistration.
1316
+ * @table_size : The number of elements in table
1313
1317
*
1314
1318
* Register a sysctl table hierarchy. @table should be a filled in ctl_table
1315
1319
* array. A completely 0 filled entry terminates the table.
@@ -1352,26 +1356,21 @@ static struct ctl_dir *sysctl_mkdir_p(struct ctl_dir *dir, const char *path)
1352
1356
*/
1353
1357
struct ctl_table_header * __register_sysctl_table (
1354
1358
struct ctl_table_set * set ,
1355
- const char * path , struct ctl_table * table )
1359
+ const char * path , struct ctl_table * table , size_t table_size )
1356
1360
{
1357
1361
struct ctl_table_root * root = set -> dir .header .root ;
1358
1362
struct ctl_table_header * header ;
1359
1363
struct ctl_dir * dir ;
1360
- struct ctl_table * entry ;
1361
1364
struct ctl_node * node ;
1362
- int nr_entries = 0 ;
1363
-
1364
- list_for_each_table_entry (entry , table )
1365
- nr_entries ++ ;
1366
1365
1367
1366
header = kzalloc (sizeof (struct ctl_table_header ) +
1368
- sizeof (struct ctl_node )* nr_entries , GFP_KERNEL_ACCOUNT );
1367
+ sizeof (struct ctl_node )* table_size , GFP_KERNEL_ACCOUNT );
1369
1368
if (!header )
1370
1369
return NULL ;
1371
1370
1372
1371
node = (struct ctl_node * )(header + 1 );
1373
- init_header (header , root , set , node , table );
1374
- if (sysctl_check_table (path , table ))
1372
+ init_header (header , root , set , node , table , table_size );
1373
+ if (sysctl_check_table (path , header ))
1375
1374
goto fail ;
1376
1375
1377
1376
spin_lock (& sysctl_lock );
@@ -1401,7 +1400,7 @@ struct ctl_table_header *__register_sysctl_table(
1401
1400
}
1402
1401
1403
1402
/**
1404
- * register_sysctl - register a sysctl table
1403
+ * register_sysctl_sz - register a sysctl table
1405
1404
* @path: The path to the directory the sysctl table is in. If the path
1406
1405
* doesn't exist we will create it for you.
1407
1406
* @table: the table structure. The calller must ensure the life of the @table
@@ -1411,18 +1410,20 @@ struct ctl_table_header *__register_sysctl_table(
1411
1410
* to call unregister_sysctl_table() and can instead use something like
1412
1411
* register_sysctl_init() which does not care for the result of the syctl
1413
1412
* registration.
1413
+ * @table_size: The number of elements in table.
1414
1414
*
1415
1415
* Register a sysctl table. @table should be a filled in ctl_table
1416
1416
* array. A completely 0 filled entry terminates the table.
1417
1417
*
1418
1418
* See __register_sysctl_table for more details.
1419
1419
*/
1420
- struct ctl_table_header * register_sysctl (const char * path , struct ctl_table * table )
1420
+ struct ctl_table_header * register_sysctl_sz (const char * path , struct ctl_table * table ,
1421
+ size_t table_size )
1421
1422
{
1422
1423
return __register_sysctl_table (& sysctl_table_root .default_set ,
1423
- path , table );
1424
+ path , table , table_size );
1424
1425
}
1425
- EXPORT_SYMBOL (register_sysctl );
1426
+ EXPORT_SYMBOL (register_sysctl_sz );
1426
1427
1427
1428
/**
1428
1429
* __register_sysctl_init() - register sysctl table to path
@@ -1433,6 +1434,7 @@ EXPORT_SYMBOL(register_sysctl);
1433
1434
* lifetime use of the sysctl.
1434
1435
* @table_name: The name of sysctl table, only used for log printing when
1435
1436
* registration fails
1437
+ * @table_size: The number of elements in table
1436
1438
*
1437
1439
* The sysctl interface is used by userspace to query or modify at runtime
1438
1440
* a predefined value set on a variable. These variables however have default
@@ -1445,12 +1447,12 @@ EXPORT_SYMBOL(register_sysctl);
1445
1447
* Context: if your base directory does not exist it will be created for you.
1446
1448
*/
1447
1449
void __init __register_sysctl_init (const char * path , struct ctl_table * table ,
1448
- const char * table_name )
1450
+ const char * table_name , size_t table_size )
1449
1451
{
1450
- struct ctl_table_header * hdr = register_sysctl (path , table );
1452
+ struct ctl_table_header * hdr = register_sysctl_sz (path , table , table_size );
1451
1453
1452
1454
if (unlikely (!hdr )) {
1453
- pr_err ("failed when register_sysctl %s to %s\n" , table_name , path );
1455
+ pr_err ("failed when register_sysctl_sz %s to %s\n" , table_name , path );
1454
1456
return ;
1455
1457
}
1456
1458
kmemleak_not_leak (hdr );
@@ -1471,7 +1473,7 @@ static void put_links(struct ctl_table_header *header)
1471
1473
if (IS_ERR (core_parent ))
1472
1474
return ;
1473
1475
1474
- list_for_each_table_entry (entry , header -> ctl_table ) {
1476
+ list_for_each_table_entry (entry , header ) {
1475
1477
struct ctl_table_header * link_head ;
1476
1478
struct ctl_table * link ;
1477
1479
const char * name = entry -> procname ;
@@ -1535,7 +1537,7 @@ void setup_sysctl_set(struct ctl_table_set *set,
1535
1537
{
1536
1538
memset (set , 0 , sizeof (* set ));
1537
1539
set -> is_seen = is_seen ;
1538
- init_header (& set -> dir .header , root , set , NULL , root_table );
1540
+ init_header (& set -> dir .header , root , set , NULL , root_table , 1 );
1539
1541
}
1540
1542
1541
1543
void retire_sysctl_set (struct ctl_table_set * set )
0 commit comments