1919#include <linux/kmemleak.h>
2020#include "internal.h"
2121
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++)
2425
2526static const struct dentry_operations proc_sys_dentry_operations ;
2627static const struct file_operations proc_sys_file_operations ;
@@ -43,7 +44,7 @@ static struct ctl_table sysctl_mount_point[] = {
4344 */
4445struct ctl_table_header * register_sysctl_mount_point (const char * path )
4546{
46- return register_sysctl (path , sysctl_mount_point );
47+ return register_sysctl_sz (path , sysctl_mount_point , 0 );
4748}
4849EXPORT_SYMBOL (register_sysctl_mount_point );
4950
@@ -188,9 +189,10 @@ static void erase_entry(struct ctl_table_header *head, struct ctl_table *entry)
188189
189190static void init_header (struct ctl_table_header * head ,
190191 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 )
192193{
193194 head -> ctl_table = table ;
195+ head -> ctl_table_size = table_size ;
194196 head -> ctl_table_arg = table ;
195197 head -> used = 0 ;
196198 head -> count = 1 ;
@@ -204,7 +206,7 @@ static void init_header(struct ctl_table_header *head,
204206 if (node ) {
205207 struct ctl_table * entry ;
206208
207- list_for_each_table_entry (entry , table ) {
209+ list_for_each_table_entry (entry , head ) {
208210 node -> header = head ;
209211 node ++ ;
210212 }
@@ -215,7 +217,7 @@ static void erase_header(struct ctl_table_header *head)
215217{
216218 struct ctl_table * entry ;
217219
218- list_for_each_table_entry (entry , head -> ctl_table )
220+ list_for_each_table_entry (entry , head )
219221 erase_entry (head , entry );
220222}
221223
@@ -242,7 +244,7 @@ static int insert_header(struct ctl_dir *dir, struct ctl_table_header *header)
242244 err = insert_links (header );
243245 if (err )
244246 goto fail_links ;
245- list_for_each_table_entry (entry , header -> ctl_table ) {
247+ list_for_each_table_entry (entry , header ) {
246248 err = insert_entry (header , entry );
247249 if (err )
248250 goto fail ;
@@ -973,7 +975,7 @@ static struct ctl_dir *new_dir(struct ctl_table_set *set,
973975 memcpy (new_name , name , namelen );
974976 table [0 ].procname = new_name ;
975977 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 );
977979
978980 return new ;
979981}
@@ -1125,11 +1127,11 @@ static int sysctl_check_table_array(const char *path, struct ctl_table *table)
11251127 return err ;
11261128}
11271129
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 )
11291131{
11301132 struct ctl_table * entry ;
11311133 int err = 0 ;
1132- list_for_each_table_entry (entry , table ) {
1134+ list_for_each_table_entry (entry , header ) {
11331135 if ((entry -> proc_handler == proc_dostring ) ||
11341136 (entry -> proc_handler == proc_dobool ) ||
11351137 (entry -> proc_handler == proc_dointvec ) ||
@@ -1159,8 +1161,7 @@ static int sysctl_check_table(const char *path, struct ctl_table *table)
11591161 return err ;
11601162}
11611163
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 )
11641165{
11651166 struct ctl_table * link_table , * entry , * link ;
11661167 struct ctl_table_header * links ;
@@ -1170,7 +1171,7 @@ static struct ctl_table_header *new_links(struct ctl_dir *dir, struct ctl_table
11701171
11711172 name_bytes = 0 ;
11721173 nr_entries = 0 ;
1173- list_for_each_table_entry (entry , table ) {
1174+ list_for_each_table_entry (entry , head ) {
11741175 nr_entries ++ ;
11751176 name_bytes += strlen (entry -> procname ) + 1 ;
11761177 }
@@ -1189,31 +1190,33 @@ static struct ctl_table_header *new_links(struct ctl_dir *dir, struct ctl_table
11891190 link_name = (char * )& link_table [nr_entries + 1 ];
11901191 link = link_table ;
11911192
1192- list_for_each_table_entry (entry , table ) {
1193+ list_for_each_table_entry (entry , head ) {
11931194 int len = strlen (entry -> procname ) + 1 ;
11941195 memcpy (link_name , entry -> procname , len );
11951196 link -> procname = link_name ;
11961197 link -> mode = S_IFLNK |S_IRWXUGO ;
1197- link -> data = link_root ;
1198+ link -> data = head -> root ;
11981199 link_name += len ;
11991200 link ++ ;
12001201 }
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 );
12021204 links -> nreg = nr_entries ;
12031205
12041206 return links ;
12051207}
12061208
12071209static 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 )
12091212{
1210- struct ctl_table_header * head ;
1213+ struct ctl_table_header * tmp_head ;
12111214 struct ctl_table * entry , * link ;
12121215
12131216 /* 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 ) {
12151218 const char * procname = entry -> procname ;
1216- link = find_entry (& head , dir , procname , strlen (procname ));
1219+ link = find_entry (& tmp_head , dir , procname , strlen (procname ));
12171220 if (!link )
12181221 return false;
12191222 if (S_ISDIR (link -> mode ) && S_ISDIR (entry -> mode ))
@@ -1224,10 +1227,10 @@ static bool get_links(struct ctl_dir *dir,
12241227 }
12251228
12261229 /* 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 ) {
12281231 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 ++ ;
12311234 }
12321235 return true;
12331236}
@@ -1246,21 +1249,21 @@ static int insert_links(struct ctl_table_header *head)
12461249 if (IS_ERR (core_parent ))
12471250 return 0 ;
12481251
1249- if (get_links (core_parent , head -> ctl_table , head -> root ))
1252+ if (get_links (core_parent , head , head -> root ))
12501253 return 0 ;
12511254
12521255 core_parent -> header .nreg ++ ;
12531256 spin_unlock (& sysctl_lock );
12541257
1255- links = new_links (core_parent , head -> ctl_table , head -> root );
1258+ links = new_links (core_parent , head );
12561259
12571260 spin_lock (& sysctl_lock );
12581261 err = - ENOMEM ;
12591262 if (!links )
12601263 goto out ;
12611264
12621265 err = 0 ;
1263- if (get_links (core_parent , head -> ctl_table , head -> root )) {
1266+ if (get_links (core_parent , head , head -> root )) {
12641267 kfree (links );
12651268 goto out ;
12661269 }
@@ -1310,6 +1313,7 @@ static struct ctl_dir *sysctl_mkdir_p(struct ctl_dir *dir, const char *path)
13101313 * should not be free'd after registration. So it should not be
13111314 * used on stack. It can either be a global or dynamically allocated
13121315 * by the caller and free'd later after sysctl unregistration.
1316+ * @table_size : The number of elements in table
13131317 *
13141318 * Register a sysctl table hierarchy. @table should be a filled in ctl_table
13151319 * 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)
13521356 */
13531357struct ctl_table_header * __register_sysctl_table (
13541358 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 )
13561360{
13571361 struct ctl_table_root * root = set -> dir .header .root ;
13581362 struct ctl_table_header * header ;
13591363 struct ctl_dir * dir ;
1360- struct ctl_table * entry ;
13611364 struct ctl_node * node ;
1362- int nr_entries = 0 ;
1363-
1364- list_for_each_table_entry (entry , table )
1365- nr_entries ++ ;
13661365
13671366 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 );
13691368 if (!header )
13701369 return NULL ;
13711370
13721371 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 ))
13751374 goto fail ;
13761375
13771376 spin_lock (& sysctl_lock );
@@ -1401,7 +1400,7 @@ struct ctl_table_header *__register_sysctl_table(
14011400}
14021401
14031402/**
1404- * register_sysctl - register a sysctl table
1403+ * register_sysctl_sz - register a sysctl table
14051404 * @path: The path to the directory the sysctl table is in. If the path
14061405 * doesn't exist we will create it for you.
14071406 * @table: the table structure. The calller must ensure the life of the @table
@@ -1411,18 +1410,20 @@ struct ctl_table_header *__register_sysctl_table(
14111410 * to call unregister_sysctl_table() and can instead use something like
14121411 * register_sysctl_init() which does not care for the result of the syctl
14131412 * registration.
1413+ * @table_size: The number of elements in table.
14141414 *
14151415 * Register a sysctl table. @table should be a filled in ctl_table
14161416 * array. A completely 0 filled entry terminates the table.
14171417 *
14181418 * See __register_sysctl_table for more details.
14191419 */
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 )
14211422{
14221423 return __register_sysctl_table (& sysctl_table_root .default_set ,
1423- path , table );
1424+ path , table , table_size );
14241425}
1425- EXPORT_SYMBOL (register_sysctl );
1426+ EXPORT_SYMBOL (register_sysctl_sz );
14261427
14271428/**
14281429 * __register_sysctl_init() - register sysctl table to path
@@ -1433,6 +1434,7 @@ EXPORT_SYMBOL(register_sysctl);
14331434 * lifetime use of the sysctl.
14341435 * @table_name: The name of sysctl table, only used for log printing when
14351436 * registration fails
1437+ * @table_size: The number of elements in table
14361438 *
14371439 * The sysctl interface is used by userspace to query or modify at runtime
14381440 * a predefined value set on a variable. These variables however have default
@@ -1445,12 +1447,12 @@ EXPORT_SYMBOL(register_sysctl);
14451447 * Context: if your base directory does not exist it will be created for you.
14461448 */
14471449void __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 )
14491451{
1450- struct ctl_table_header * hdr = register_sysctl (path , table );
1452+ struct ctl_table_header * hdr = register_sysctl_sz (path , table , table_size );
14511453
14521454 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 );
14541456 return ;
14551457 }
14561458 kmemleak_not_leak (hdr );
@@ -1471,7 +1473,7 @@ static void put_links(struct ctl_table_header *header)
14711473 if (IS_ERR (core_parent ))
14721474 return ;
14731475
1474- list_for_each_table_entry (entry , header -> ctl_table ) {
1476+ list_for_each_table_entry (entry , header ) {
14751477 struct ctl_table_header * link_head ;
14761478 struct ctl_table * link ;
14771479 const char * name = entry -> procname ;
@@ -1535,7 +1537,7 @@ void setup_sysctl_set(struct ctl_table_set *set,
15351537{
15361538 memset (set , 0 , sizeof (* set ));
15371539 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 );
15391541}
15401542
15411543void retire_sysctl_set (struct ctl_table_set * set )
0 commit comments