Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

ipv6: introduce secret_stable to ipv6_devconf

This patch implements the procfs logic for the stable_address knob:
The secret is formatted as an ipv6 address and will be stored per
interface and per namespace. We track initialized flag and return EIO
errors until the secret is set.

We don't inherit the secret to newly created namespaces.

Cc: Erik Kline <ek@google.com>
Cc: Fernando Gont <fgont@si6networks.com>
Cc: Lorenzo Colitti <lorenzo@google.com>
Cc: YOSHIFUJI Hideaki/吉藤英明 <hideaki.yoshifuji@miraclelinux.com>
Signed-off-by: Hannes Frederic Sowa <hannes@stressinduktion.org>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Hannes Frederic Sowa and committed by
David S. Miller
3d1bec99 ab2bb324

+73
+4
include/linux/ipv6.h
··· 53 53 __s32 ndisc_notify; 54 54 __s32 suppress_frag_ndisc; 55 55 __s32 accept_ra_mtu; 56 + struct ipv6_stable_secret { 57 + bool initialized; 58 + struct in6_addr secret; 59 + } stable_secret; 56 60 void *sysctl; 57 61 }; 58 62
+1
include/uapi/linux/ipv6.h
··· 170 170 DEVCONF_ACCEPT_RA_FROM_LOCAL, 171 171 DEVCONF_USE_OPTIMISTIC, 172 172 DEVCONF_ACCEPT_RA_MTU, 173 + DEVCONF_STABLE_SECRET, 173 174 DEVCONF_MAX 174 175 }; 175 176
+68
net/ipv6/addrconf.c
··· 46 46 #include <linux/socket.h> 47 47 #include <linux/sockios.h> 48 48 #include <linux/net.h> 49 + #include <linux/inet.h> 49 50 #include <linux/in6.h> 50 51 #include <linux/netdevice.h> 51 52 #include <linux/if_addr.h> ··· 102 101 #endif 103 102 104 103 #define INFINITY_LIFE_TIME 0xFFFFFFFF 104 + 105 + #define IPV6_MAX_STRLEN \ 106 + sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255") 105 107 106 108 static inline u32 cstamp_delta(unsigned long cstamp) 107 109 { ··· 206 202 .accept_dad = 1, 207 203 .suppress_frag_ndisc = 1, 208 204 .accept_ra_mtu = 1, 205 + .stable_secret = { 206 + .initialized = false, 207 + } 209 208 }; 210 209 211 210 static struct ipv6_devconf ipv6_devconf_dflt __read_mostly = { ··· 247 240 .accept_dad = 1, 248 241 .suppress_frag_ndisc = 1, 249 242 .accept_ra_mtu = 1, 243 + .stable_secret = { 244 + .initialized = false, 245 + }, 250 246 }; 251 247 252 248 /* Check if a valid qdisc is available */ ··· 4440 4430 array[DEVCONF_SUPPRESS_FRAG_NDISC] = cnf->suppress_frag_ndisc; 4441 4431 array[DEVCONF_ACCEPT_RA_FROM_LOCAL] = cnf->accept_ra_from_local; 4442 4432 array[DEVCONF_ACCEPT_RA_MTU] = cnf->accept_ra_mtu; 4433 + /* we omit DEVCONF_STABLE_SECRET for now */ 4443 4434 } 4444 4435 4445 4436 static inline size_t inet6_ifla6_size(void) ··· 5085 5074 return ret; 5086 5075 } 5087 5076 5077 + static int addrconf_sysctl_stable_secret(struct ctl_table *ctl, int write, 5078 + void __user *buffer, size_t *lenp, 5079 + loff_t *ppos) 5080 + { 5081 + int err; 5082 + struct in6_addr addr; 5083 + char str[IPV6_MAX_STRLEN]; 5084 + struct ctl_table lctl = *ctl; 5085 + struct ipv6_stable_secret *secret = ctl->data; 5086 + 5087 + lctl.maxlen = IPV6_MAX_STRLEN; 5088 + lctl.data = str; 5089 + 5090 + if (!rtnl_trylock()) 5091 + return restart_syscall(); 5092 + 5093 + if (!write && !secret->initialized) { 5094 + err = -EIO; 5095 + goto out; 5096 + } 5097 + 5098 + if (!write) { 5099 + err = snprintf(str, sizeof(str), "%pI6", 5100 + &secret->secret); 5101 + if (err >= sizeof(str)) { 5102 + err = -EIO; 5103 + goto out; 5104 + } 5105 + } 5106 + 5107 + err = proc_dostring(&lctl, write, buffer, lenp, ppos); 5108 + if (err || !write) 5109 + goto out; 5110 + 5111 + if (in6_pton(str, -1, addr.in6_u.u6_addr8, -1, NULL) != 1) { 5112 + err = -EIO; 5113 + goto out; 5114 + } 5115 + 5116 + secret->initialized = true; 5117 + secret->secret = addr; 5118 + 5119 + out: 5120 + rtnl_unlock(); 5121 + 5122 + return err; 5123 + } 5088 5124 5089 5125 static struct addrconf_sysctl_table 5090 5126 { ··· 5405 5347 .proc_handler = proc_dointvec, 5406 5348 }, 5407 5349 { 5350 + .procname = "stable_secret", 5351 + .data = &ipv6_devconf.stable_secret, 5352 + .maxlen = IPV6_MAX_STRLEN, 5353 + .mode = 0600, 5354 + .proc_handler = addrconf_sysctl_stable_secret, 5355 + }, 5356 + { 5408 5357 /* sentinel */ 5409 5358 } 5410 5359 }, ··· 5506 5441 /* these will be inherited by all namespaces */ 5507 5442 dflt->autoconf = ipv6_defaults.autoconf; 5508 5443 dflt->disable_ipv6 = ipv6_defaults.disable_ipv6; 5444 + 5445 + dflt->stable_secret.initialized = false; 5446 + all->stable_secret.initialized = false; 5509 5447 5510 5448 net->ipv6.devconf_all = all; 5511 5449 net->ipv6.devconf_dflt = dflt;