@@ -210,6 +210,19 @@ char *devconfs6[] = {
210
210
#define MAX_CONF_OPT_PATH IFNAMSIZ+60
211
211
#define MAX_STR_CONF_LEN 200
212
212
213
+ static const char * unix_conf_entries [] = {
214
+ "max_dgram_qlen" ,
215
+ };
216
+
217
+ /*
218
+ * MAX_CONF_UNIX_PATH = (sizeof(CONF_UNIX_FMT) - strlen("%s"))
219
+ * + MAX_CONF_UNIX_OPT_PATH
220
+ */
221
+ #define CONF_UNIX_BASE "net/unix"
222
+ #define CONF_UNIX_FMT CONF_UNIX_BASE"/%s"
223
+ #define MAX_CONF_UNIX_OPT_PATH 32
224
+ #define MAX_CONF_UNIX_PATH (sizeof(CONF_UNIX_FMT) + MAX_CONF_UNIX_OPT_PATH - 2)
225
+
213
226
static int net_conf_op (char * tgt , SysctlEntry * * conf , int n , int op , char * proto ,
214
227
struct sysctl_req * req , char (* path )[MAX_CONF_OPT_PATH ], int size ,
215
228
char * * devconfs , SysctlEntry * * def_conf )
@@ -339,6 +352,72 @@ static int ipv6_conf_op(char *tgt, SysctlEntry **conf, int n, int op, SysctlEntr
339
352
devconfs6 , def_conf );
340
353
}
341
354
355
+ static int unix_conf_op (SysctlEntry * * * rconf , size_t * n , int op )
356
+ {
357
+ int i , ret = -1 , flags = 0 ;
358
+ char path [ARRAY_SIZE (unix_conf_entries )][MAX_CONF_UNIX_PATH ] = { };
359
+ struct sysctl_req req [ARRAY_SIZE (unix_conf_entries )] = { };
360
+ SysctlEntry * * conf = * rconf ;
361
+
362
+ if (* n != ARRAY_SIZE (unix_conf_entries )) {
363
+ pr_err ("unix: Unexpected entries in config (%zu %zu)\n" ,
364
+ * n , ARRAY_SIZE (unix_conf_entries ));
365
+ return - EINVAL ;
366
+ }
367
+
368
+ if (opts .weak_sysctls || op == CTL_READ )
369
+ flags = CTL_FLAGS_OPTIONAL ;
370
+
371
+ for (i = 0 ; i < * n ; i ++ ) {
372
+ snprintf (path [i ], MAX_CONF_UNIX_PATH , CONF_UNIX_FMT ,
373
+ unix_conf_entries [i ]);
374
+ req [i ].name = path [i ];
375
+ req [i ].flags = flags ;
376
+
377
+ switch (conf [i ]-> type ) {
378
+ case SYSCTL_TYPE__CTL_32 :
379
+ req [i ].type = CTL_32 ;
380
+ req [i ].arg = & conf [i ]-> iarg ;
381
+ break ;
382
+ default :
383
+ pr_err ("unix: Unknown config type %d\n" ,
384
+ conf [i ]-> type );
385
+ return -1 ;
386
+ }
387
+ }
388
+
389
+ ret = sysctl_op (req , * n , op , CLONE_NEWNET );
390
+ if (ret < 0 ) {
391
+ pr_err ("unix: Failed to %s %s/<confs>\n" ,
392
+ (op == CTL_READ ) ? "read" : "write" ,
393
+ CONF_UNIX_BASE );
394
+ return -1 ;
395
+ }
396
+
397
+ if (op == CTL_READ ) {
398
+ bool has_entries = false;
399
+
400
+ for (i = 0 ; i < * n ; i ++ ) {
401
+ if (req [i ].flags & CTL_FLAGS_HAS ) {
402
+ conf [i ]-> has_iarg = true;
403
+ if (!has_entries )
404
+ has_entries = true;
405
+ }
406
+ }
407
+
408
+ /*
409
+ * Zap the whole section of data.
410
+ * Unix conf is optional.
411
+ */
412
+ if (!has_entries ) {
413
+ * n = 0 ;
414
+ * rconf = NULL ;
415
+ }
416
+ }
417
+
418
+ return 0 ;
419
+ }
420
+
342
421
/*
343
422
* I case if some entry is missing in
344
423
* the kernel, simply write DEVCONFS_UNUSED
@@ -1824,6 +1903,8 @@ static int dump_netns_conf(struct ns_id *ns, struct cr_imgset *fds)
1824
1903
int ret = -1 ;
1825
1904
int i ;
1826
1905
NetnsEntry netns = NETNS_ENTRY__INIT ;
1906
+ SysctlEntry * unix_confs = NULL ;
1907
+ size_t sizex = ARRAY_SIZE (unix_conf_entries );
1827
1908
SysctlEntry * def_confs4 = NULL , * all_confs4 = NULL ;
1828
1909
int size4 = ARRAY_SIZE (devconfs4 );
1829
1910
SysctlEntry * def_confs6 = NULL , * all_confs6 = NULL ;
@@ -1840,7 +1921,8 @@ static int dump_netns_conf(struct ns_id *ns, struct cr_imgset *fds)
1840
1921
o_buf = buf = xmalloc (
1841
1922
i * (sizeof (NetnsId * ) + sizeof (NetnsId )) +
1842
1923
size4 * (sizeof (SysctlEntry * ) + sizeof (SysctlEntry )) * 2 +
1843
- size6 * (sizeof (SysctlEntry * ) + sizeof (SysctlEntry )) * 2
1924
+ size6 * (sizeof (SysctlEntry * ) + sizeof (SysctlEntry )) * 2 +
1925
+ sizex * (sizeof (SysctlEntry * ) + sizeof (SysctlEntry ))
1844
1926
);
1845
1927
if (!buf )
1846
1928
goto out ;
@@ -1896,6 +1978,16 @@ static int dump_netns_conf(struct ns_id *ns, struct cr_imgset *fds)
1896
1978
}
1897
1979
}
1898
1980
1981
+ netns .n_unix_conf = sizex ;
1982
+ netns .unix_conf = xptr_pull_s (& buf , sizex * sizeof (SysctlEntry * ));
1983
+ unix_confs = xptr_pull_s (& buf , sizex * sizeof (SysctlEntry ));
1984
+
1985
+ for (i = 0 ; i < sizex ; i ++ ) {
1986
+ sysctl_entry__init (& unix_confs [i ]);
1987
+ netns .unix_conf [i ] = & unix_confs [i ];
1988
+ netns .unix_conf [i ]-> type = SYSCTL_TYPE__CTL_32 ;
1989
+ }
1990
+
1899
1991
ret = ipv4_conf_op ("default" , netns .def_conf4 , size4 , CTL_READ , NULL );
1900
1992
if (ret < 0 )
1901
1993
goto err_free ;
@@ -1910,6 +2002,10 @@ static int dump_netns_conf(struct ns_id *ns, struct cr_imgset *fds)
1910
2002
if (ret < 0 )
1911
2003
goto err_free ;
1912
2004
2005
+ ret = unix_conf_op (& netns .unix_conf , & netns .n_unix_conf , CTL_READ );
2006
+ if (ret < 0 )
2007
+ goto err_free ;
2008
+
1913
2009
ret = pb_write_one (img_from_set (fds , CR_FD_NETNS ), & netns , PB_NETNS );
1914
2010
err_free :
1915
2011
xfree (o_buf );
@@ -2122,6 +2218,12 @@ static int restore_netns_conf(struct ns_id *ns)
2122
2218
ret = ipv6_conf_op ("default" , (netns )-> def_conf6 , (netns )-> n_def_conf6 , CTL_WRITE , NULL );
2123
2219
}
2124
2220
2221
+ if ((netns )-> unix_conf ) {
2222
+ ret = unix_conf_op (& (netns )-> unix_conf , & (netns )-> n_unix_conf , CTL_WRITE );
2223
+ if (ret )
2224
+ goto out ;
2225
+ }
2226
+
2125
2227
ns -> net .netns = netns ;
2126
2228
out :
2127
2229
return ret ;
0 commit comments