summaryrefslogtreecommitdiffstats
path: root/lib/nlattr.c
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2018-09-26 05:15:32 -0400
committerDavid S. Miller <davem@davemloft.net>2018-09-28 13:24:39 -0400
commitc29f1845b2b22974411278bad3a2ac0b7815dfb4 (patch)
tree068b778699737fdf5bc184913423daa334412c1a /lib/nlattr.c
parent48fde90a78f8c67e2bec5061f9725fe363519feb (diff)
netlink: move extack setting into validate_nla()
This unifies the code between nla_parse() which sets the bad attribute pointer and an error message, and nla_validate() which only sets the bad attribute pointer. It also cleans up the code for NLA_REJECT and paves the way for nested policy validation, as it will allow us to easily skip setting the "generic" message without any extra args like the **error_msg now, just passing the extack through is now enough. While at it, remove the unnecessary label in nla_parse(). Suggested-by: David Ahern <dsahern@gmail.com> Signed-off-by: Johannes Berg <johannes.berg@intel.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'lib/nlattr.c')
-rw-r--r--lib/nlattr.c68
1 files changed, 36 insertions, 32 deletions
diff --git a/lib/nlattr.c b/lib/nlattr.c
index e2e5b38394d5..6e03d650bec4 100644
--- a/lib/nlattr.c
+++ b/lib/nlattr.c
@@ -69,10 +69,11 @@ static int validate_nla_bitfield32(const struct nlattr *nla,
69 69
70static int validate_nla(const struct nlattr *nla, int maxtype, 70static int validate_nla(const struct nlattr *nla, int maxtype,
71 const struct nla_policy *policy, 71 const struct nla_policy *policy,
72 const char **error_msg) 72 struct netlink_ext_ack *extack)
73{ 73{
74 const struct nla_policy *pt; 74 const struct nla_policy *pt;
75 int minlen = 0, attrlen = nla_len(nla), type = nla_type(nla); 75 int minlen = 0, attrlen = nla_len(nla), type = nla_type(nla);
76 int err = -ERANGE;
76 77
77 if (type <= 0 || type > maxtype) 78 if (type <= 0 || type > maxtype)
78 return 0; 79 return 0;
@@ -90,24 +91,31 @@ static int validate_nla(const struct nlattr *nla, int maxtype,
90 switch (pt->type) { 91 switch (pt->type) {
91 case NLA_EXACT_LEN: 92 case NLA_EXACT_LEN:
92 if (attrlen != pt->len) 93 if (attrlen != pt->len)
93 return -ERANGE; 94 goto out_err;
94 break; 95 break;
95 96
96 case NLA_REJECT: 97 case NLA_REJECT:
97 if (pt->validation_data && error_msg) 98 if (extack && pt->validation_data) {
98 *error_msg = pt->validation_data; 99 NL_SET_BAD_ATTR(extack, nla);
99 return -EINVAL; 100 extack->_msg = pt->validation_data;
101 return -EINVAL;
102 }
103 err = -EINVAL;
104 goto out_err;
100 105
101 case NLA_FLAG: 106 case NLA_FLAG:
102 if (attrlen > 0) 107 if (attrlen > 0)
103 return -ERANGE; 108 goto out_err;
104 break; 109 break;
105 110
106 case NLA_BITFIELD32: 111 case NLA_BITFIELD32:
107 if (attrlen != sizeof(struct nla_bitfield32)) 112 if (attrlen != sizeof(struct nla_bitfield32))
108 return -ERANGE; 113 goto out_err;
109 114
110 return validate_nla_bitfield32(nla, pt->validation_data); 115 err = validate_nla_bitfield32(nla, pt->validation_data);
116 if (err)
117 goto out_err;
118 break;
111 119
112 case NLA_NUL_STRING: 120 case NLA_NUL_STRING:
113 if (pt->len) 121 if (pt->len)
@@ -115,13 +123,15 @@ static int validate_nla(const struct nlattr *nla, int maxtype,
115 else 123 else
116 minlen = attrlen; 124 minlen = attrlen;
117 125
118 if (!minlen || memchr(nla_data(nla), '\0', minlen) == NULL) 126 if (!minlen || memchr(nla_data(nla), '\0', minlen) == NULL) {
119 return -EINVAL; 127 err = -EINVAL;
128 goto out_err;
129 }
120 /* fall through */ 130 /* fall through */
121 131
122 case NLA_STRING: 132 case NLA_STRING:
123 if (attrlen < 1) 133 if (attrlen < 1)
124 return -ERANGE; 134 goto out_err;
125 135
126 if (pt->len) { 136 if (pt->len) {
127 char *buf = nla_data(nla); 137 char *buf = nla_data(nla);
@@ -130,13 +140,13 @@ static int validate_nla(const struct nlattr *nla, int maxtype,
130 attrlen--; 140 attrlen--;
131 141
132 if (attrlen > pt->len) 142 if (attrlen > pt->len)
133 return -ERANGE; 143 goto out_err;
134 } 144 }
135 break; 145 break;
136 146
137 case NLA_BINARY: 147 case NLA_BINARY:
138 if (pt->len && attrlen > pt->len) 148 if (pt->len && attrlen > pt->len)
139 return -ERANGE; 149 goto out_err;
140 break; 150 break;
141 151
142 case NLA_NESTED: 152 case NLA_NESTED:
@@ -152,10 +162,13 @@ static int validate_nla(const struct nlattr *nla, int maxtype,
152 minlen = nla_attr_minlen[pt->type]; 162 minlen = nla_attr_minlen[pt->type];
153 163
154 if (attrlen < minlen) 164 if (attrlen < minlen)
155 return -ERANGE; 165 goto out_err;
156 } 166 }
157 167
158 return 0; 168 return 0;
169out_err:
170 NL_SET_ERR_MSG_ATTR(extack, nla, "Attribute failed policy validation");
171 return err;
159} 172}
160 173
161/** 174/**
@@ -180,12 +193,10 @@ int nla_validate(const struct nlattr *head, int len, int maxtype,
180 int rem; 193 int rem;
181 194
182 nla_for_each_attr(nla, head, len, rem) { 195 nla_for_each_attr(nla, head, len, rem) {
183 int err = validate_nla(nla, maxtype, policy, NULL); 196 int err = validate_nla(nla, maxtype, policy, extack);
184 197
185 if (err < 0) { 198 if (err < 0)
186 NL_SET_BAD_ATTR(extack, nla);
187 return err; 199 return err;
188 }
189 } 200 }
190 201
191 return 0; 202 return 0;
@@ -241,7 +252,7 @@ int nla_parse(struct nlattr **tb, int maxtype, const struct nlattr *head,
241 struct netlink_ext_ack *extack) 252 struct netlink_ext_ack *extack)
242{ 253{
243 const struct nlattr *nla; 254 const struct nlattr *nla;
244 int rem, err; 255 int rem;
245 256
246 memset(tb, 0, sizeof(struct nlattr *) * (maxtype + 1)); 257 memset(tb, 0, sizeof(struct nlattr *) * (maxtype + 1));
247 258
@@ -249,17 +260,12 @@ int nla_parse(struct nlattr **tb, int maxtype, const struct nlattr *head,
249 u16 type = nla_type(nla); 260 u16 type = nla_type(nla);
250 261
251 if (type > 0 && type <= maxtype) { 262 if (type > 0 && type <= maxtype) {
252 static const char _msg[] = "Attribute failed policy validation";
253 const char *msg = _msg;
254
255 if (policy) { 263 if (policy) {
256 err = validate_nla(nla, maxtype, policy, &msg); 264 int err = validate_nla(nla, maxtype, policy,
257 if (err < 0) { 265 extack);
258 NL_SET_BAD_ATTR(extack, nla); 266
259 if (extack) 267 if (err < 0)
260 extack->_msg = msg; 268 return err;
261 goto errout;
262 }
263 } 269 }
264 270
265 tb[type] = (struct nlattr *)nla; 271 tb[type] = (struct nlattr *)nla;
@@ -270,9 +276,7 @@ int nla_parse(struct nlattr **tb, int maxtype, const struct nlattr *head,
270 pr_warn_ratelimited("netlink: %d bytes leftover after parsing attributes in process `%s'.\n", 276 pr_warn_ratelimited("netlink: %d bytes leftover after parsing attributes in process `%s'.\n",
271 rem, current->comm); 277 rem, current->comm);
272 278
273 err = 0; 279 return 0;
274errout:
275 return err;
276} 280}
277EXPORT_SYMBOL(nla_parse); 281EXPORT_SYMBOL(nla_parse);
278 282