Thomas Graf wrote:
> * [EMAIL PROTECTED] <[EMAIL PROTECTED]> 2006-09-21 12:57
> 
>>At the suggestion of Thomas Graf, rewrite NetLabel's use of Netlink attributes
>>to better follow the common Netlink attribute usage.
>>
>>Signed-off-by: Paul Moore <[EMAIL PROTECTED]>
>>---
>> net/netlabel/netlabel_cipso_v4.c  |  593 
>> +++++++++++++++++++++++++-------------
>> net/netlabel/netlabel_cipso_v4.h  |  235 +++++----------
>> net/netlabel/netlabel_mgmt.c      |  531 +++++++++++++++++-----------------
>> net/netlabel/netlabel_mgmt.h      |  213 ++++---------
>> net/netlabel/netlabel_unlabeled.c |   77 ++--
>> net/netlabel/netlabel_unlabeled.h |   41 +-
>> 6 files changed, 875 insertions(+), 815 deletions(-)
>>
>> {snip}
>>
>>@@ -128,28 +156,44 @@ static int netlbl_cipsov4_add_std(u32 do
>>      }
>>      doi_def->type = CIPSO_V4_MAP_STD;
>> 
>>-     for (iter = 0; iter < num_tags; iter++) {
>>-             if (msg_len < NETLBL_LEN_U8)
>>-                     goto add_std_failure;
>>-             doi_def->tags[iter] = netlbl_getinc_u8(&msg, &msg_len);
>>-             switch (doi_def->tags[iter]) {
>>-             case CIPSO_V4_TAG_RBITMAP:
>>-                     break;
>>-             default:
>>-                     goto add_std_failure;
>>+     nla_for_each_attr(nla_a,
>>+                       nla_data(info->attrs[NLBL_CIPSOV4_A_TAGLST]),
>>+                       nla_len(info->attrs[NLBL_CIPSOV4_A_TAGLST]),
>>+                       nla_a_rem)
> 
> 
> You can use nla_for_each_nested() here.

Huh, look at that, guess I didn't scroll down far enough in the header
file :)  Thanks.

>>+             if (nla_a->nla_type == NLBL_CIPSOV4_A_TAG) {
>>+                     if (iter > CIPSO_V4_TAG_MAXCNT)
>>+                             goto add_std_failure;
>>+                     doi_def->tags[iter++] = nla_get_u8(nla_a);
>>              }
> 
> 
> Perfectly validated against generic policy yet flexible, I
> like this a lot.
> 
> 
> 
>>+     nla_for_each_attr(nla_a,
>>+                       nla_data(info->attrs[NLBL_CIPSOV4_A_MLSLVLLST]),
>>+                       nla_len(info->attrs[NLBL_CIPSOV4_A_MLSLVLLST]),
>>+                       nla_a_rem)
> 
> 
> Could use nla_for_each_nested() here as well.
> 
> 
>>+             if (nla_a->nla_type == NLBL_CIPSOV4_A_MLSLVL) {
>>+                     nla_for_each_attr(nla_b,
>>+                                       nla_data(nla_a),
>>+                                       nla_len(nla_a),
>>+                                       nla_b_rem)
> 
> 
> ... and again :-)
> 
> 
>>+                             switch (nla_b->nla_type) {
>>+                             case NLBL_CIPSOV4_A_MLSLVLLOC:
>>+                                     if (nla_get_u32(nla_b) >=
> 
> 
> Attributes on this level are not yet validated. 
> 

Yes, you're right, same problem with the _MLSCAT attribute.  Thanks.

>>+                                         doi_def->map.std->lvl.local_size)
>>+                                          doi_def->map.std->lvl.local_size =
>>+                                                  nla_get_u32(nla_b) + 1;
>>+                                     break;
>>+                             case NLBL_CIPSOV4_A_MLSLVLREM:
>>+                                     if (nla_get_u32(nla_b) >=
>>+                                         doi_def->map.std->lvl.cipso_size)
>>+                                          doi_def->map.std->lvl.cipso_size =
>>+                                                  nla_get_u32(nla_b) + 1;
>>+                                     break;
>>+                             }
>>+             }
>>@@ -168,68 +209,96 @@ static int netlbl_cipsov4_add_std(u32 do
>>              ret_val = -ENOMEM;
>>              goto add_std_failure;
>>      }
>>+     nla_for_each_attr(nla_a,
>>+                       nla_data(info->attrs[NLBL_CIPSOV4_A_MLSLVLLST]),
>>+                       nla_len(info->attrs[NLBL_CIPSOV4_A_MLSLVLLST]),
>>+                       nla_a_rem)
> 
> 
>>+             if (nla_a->nla_type == NLBL_CIPSOV4_A_MLSLVL) {
>>+                     nla_b = nla_find_nested(nla_a,
>>+                                             NLBL_CIPSOV4_A_MLSLVLLOC);
>>+                     nla_c = nla_find_nested(nla_a,
>>+                                             NLBL_CIPSOV4_A_MLSLVLREM);
> 
> 
> Maybe find better names for nla_a and nla_b, would enhance readability
> 

Fair enough.

>>+                     if (nla_b == NULL || nla_c == NULL)
>>+                             goto add_std_failure;
>>+                     doi_def->map.std->lvl.local[nla_get_u32(nla_b)] =
>>+                             nla_get_u32(nla_c);
>>+                     doi_def->map.std->lvl.cipso[nla_get_u32(nla_c)] =
>>+                             nla_get_u32(nla_b);
>>+             }
>> 
>>-     num_cats = netlbl_getinc_u32(&msg, &msg_len);
>>-     doi_def->map.std->cat.local_size = netlbl_getinc_u32(&msg, &msg_len);
>>-     if (doi_def->map.std->cat.local_size > CIPSO_V4_MAX_LOC_CATS)
>>-             goto add_std_failure;
>>-     doi_def->map.std->cat.local = kcalloc(doi_def->map.std->cat.local_size,
>>+     if (info->attrs[NLBL_CIPSOV4_A_MLSCATLST]) {
>>+             if (nla_validate(
>>+                         nla_data(info->attrs[NLBL_CIPSOV4_A_MLSCATLST]),
>>+                         nla_len(info->attrs[NLBL_CIPSOV4_A_MLSCATLST]),
>>+                         NLBL_CIPSOV4_A_MAX,
>>+                         netlbl_cipsov4_genl_policy) != 0)
> 
> We might want to add nla_validate_nested() to the interface as this seems
> to become a common usage.

Easy enough.  I'll make that a separate patch in the next patchset.

>>@@ -276,21 +345,20 @@ static int netlbl_cipsov4_add_pass(u32 d
>>      }
>>      doi_def->type = CIPSO_V4_MAP_PASS;
>> 
>>-     for (iter = 0; iter < num_tags; iter++) {
>>-             if (msg_len < NETLBL_LEN_U8)
>>-                     goto add_pass_failure;
>>-             doi_def->tags[iter] = netlbl_getinc_u8(&msg, &msg_len);
>>-             switch (doi_def->tags[iter]) {
>>-             case CIPSO_V4_TAG_RBITMAP:
>>-                     break;
>>-             default:
>>-                     goto add_pass_failure;
>>+     nla_for_each_attr(nla,
>>+                       nla_data(info->attrs[NLBL_CIPSOV4_A_TAGLST]),
>>+                       nla_len(info->attrs[NLBL_CIPSOV4_A_TAGLST]),
>>+                       nla_rem)
>>+             if (nla->nla_type == NLBL_CIPSOV4_A_TAG) {
>>+                     if (iter > CIPSO_V4_TAG_MAXCNT)
>>+                             goto add_pass_failure;
>>+                     doi_def->tags[iter++] = nla_get_u8(nla);
>>              }
>  
> This is duplicated code, put this into netlbl_cipsov4_get_tags()?
> 

There is actually a little bit more than that too, I see your point.
I'll make a netlbl_cipsov4_add_common().

>>@@ -353,84 +408,237 @@ add_return:
>>  * @info: the Generic NETLINK info block
>>  *
>>  * Description:
>>- * Process a user generated LIST message and respond accordingly.  Returns
>>- * zero on success and negative values on error.
>>+ * Process a user generated LIST message and respond accordingly.  While the
>>+ * response message generated by the kernel is straightforward, determining
>>+ * before hand the size of the buffer to allocate is not (we have to generate
>>+ * the message to know the size).  In order to keep this function sane what 
>>we
>>+ * do is allocate a buffer of NLMSG_GOODSIZE and try to fit the response in
>>+ * that size, if we fail then we restart with a larger buffer and try again.
>>+ * We continue in this manner until we hit a limit of failed attempts then we
>>+ * give up and just send an error message.  Returns zero on success and
>>+ * negative values on error.
>>  *
>>  */
>> static int netlbl_cipsov4_list(struct sk_buff *skb, struct genl_info *info)
>> {
>>-     int ret_val = -EINVAL;
>>+     int ret_val;
>>+     struct sk_buff *ans_skb = NULL;
>>+     u32 nlsze_mult = 1;
>>+     void *data;
>>      u32 doi;
>>-     struct nlattr *msg = netlbl_netlink_payload_data(skb);
>>-     struct sk_buff *ans_skb;
>>+     struct nlattr *nla_a;
>>+     struct nlattr *nla_b;
>>+     struct cipso_v4_doi *doi_def;
>>+     u32 iter;
>> 
>>-     if (netlbl_netlink_payload_len(skb) != NETLBL_LEN_U32)
>>+     if (!info->attrs[NLBL_CIPSOV4_A_DOI]) {
>>+             ret_val = -EINVAL;
>>              goto list_failure;
>>+     }
>> 
>>-     doi = nla_get_u32(msg);
>>-     ans_skb = cipso_v4_doi_dump(doi, NLMSG_SPACE(GENL_HDRLEN));
>>+list_start:
>>+     ans_skb = nlmsg_new(NLMSG_GOODSIZE * nlsze_mult, GFP_KERNEL);
>>      if (ans_skb == NULL) {
>>              ret_val = -ENOMEM;
>>              goto list_failure;
>>      }
>>-     netlbl_netlink_hdr_push(ans_skb,
>>-                             info->snd_pid,
>>-                             0,
>>-                             netlbl_cipsov4_gnl_family.id,
>>-                             NLBL_CIPSOV4_C_LIST);
>>+     data = netlbl_netlink_hdr_put(ans_skb,
>>+                                   info->snd_pid,
>>+                                   info->snd_seq,
>>+                                   netlbl_cipsov4_gnl_family.id,
>>+                                   0,
>>+                                   NLBL_CIPSOV4_C_LIST);
>>+     if (data == NULL) {
>>+             ret_val = -ENOMEM;
>>+             goto list_failure;
>>+     }
>>+
>>+     doi = nla_get_u32(info->attrs[NLBL_CIPSOV4_A_DOI]);
>>+
>>+     rcu_read_lock();
>>+     doi_def = cipso_v4_doi_getdef(doi);
>>+     if (doi_def == NULL) {
>>+             ret_val = -EINVAL;
>>+             goto list_failure;
>>+     }
>>+
>>+     ret_val = nla_put_u32(ans_skb, NLBL_CIPSOV4_A_MTYPE, doi_def->type);
>>+     if (ret_val != 0)
>>+             goto list_failure_lock;
>>+
>>+     nla_a = nla_nest_start(ans_skb, NLBL_CIPSOV4_A_TAGLST);
>>+     if (nla_a == NULL) {
>>+             ret_val = -ENOMEM;
>>+             goto list_failure_lock;
>>+     }
>>+     for (iter = 0;
>>+          iter < CIPSO_V4_TAG_MAXCNT &&
>>+            doi_def->tags[iter] != CIPSO_V4_TAG_INVALID;
>>+          iter++) {
>>+             ret_val = nla_put_u8(ans_skb,
>>+                                  NLBL_CIPSOV4_A_TAG,
>>+                                  doi_def->tags[iter]);
>>+             if (ret_val != 0)
>>+                     goto list_failure_lock;
>>+     }
>>+     nla_nest_end(ans_skb, nla_a);
>> 
>>-     ret_val = netlbl_netlink_snd(ans_skb, info->snd_pid);
>>+     switch (doi_def->type) {
>>+     case CIPSO_V4_MAP_STD:
>>+             nla_a = nla_nest_start(ans_skb, NLBL_CIPSOV4_A_MLSLVLLST);
>>+             if (nla_a == NULL) {
>>+                     ret_val = -ENOMEM;
>>+                     goto list_failure_lock;
>>+             }
>>+             for (iter = 0;
>>+                  iter < doi_def->map.std->lvl.local_size;
>>+                  iter++) {
>>+                     if (doi_def->map.std->lvl.local[iter] ==
>>+                         CIPSO_V4_INV_LVL)
>>+                             continue;
> 
> 
> Can you estimate the number of entries being dumped here and in the cat
> list below?
> 

It's too hard to come up with a reasonable estimate without going
through the entire list before hand, which in previous messages (might
of been off-list) you pointed out as a bad thing.  If you would prefer I
can go back to doing it that way?

>>+
>>+                     nla_b = nla_nest_start(ans_skb, NLBL_CIPSOV4_A_MLSLVL);
>>+                     if (nla_b == NULL) {
>>+                             ret_val = -ENOMEM;
>>+                             goto list_retry;
>>+                     }
>>+                     ret_val = nla_put_u32(ans_skb,
>>+                                           NLBL_CIPSOV4_A_MLSLVLLOC,
>>+                                           iter);
>>+                     if (ret_val != 0)
>>+                             goto list_retry;
>>+                     ret_val = nla_put_u32(ans_skb,
>>+                                         NLBL_CIPSOV4_A_MLSLVLREM,
>>+                                         doi_def->map.std->lvl.local[iter]);
>>+                     if (ret_val != 0)
>>+                             goto list_retry;
>>+                     nla_nest_end(ans_skb, nla_b);
>>+             }
>>+             nla_nest_end(ans_skb, nla_a);
>>+
>>+             nla_a = nla_nest_start(ans_skb, NLBL_CIPSOV4_A_MLSCATLST);
>>+             if (nla_a == NULL) {
>>+                     ret_val = -ENOMEM;
>>+                     goto list_retry;
>>+             }
>>+             for (iter = 0;
>>+                  iter < doi_def->map.std->cat.local_size;
>>+                  iter++) {
>>+                     if (doi_def->map.std->cat.local[iter] ==
>>+                         CIPSO_V4_INV_CAT)
>>+                             continue;
>>+
>>+                     nla_b = nla_nest_start(ans_skb, NLBL_CIPSOV4_A_MLSCAT);
>>+                     if (nla_b == NULL) {
>>+                             ret_val = -ENOMEM;
>>+                             goto list_retry;
>>+                     }
>>+                     ret_val = nla_put_u32(ans_skb,
>>+                                           NLBL_CIPSOV4_A_MLSCATLOC,
>>+                                           iter);
>>+                     if (ret_val != 0)
>>+                             goto list_retry;
>>+                     ret_val = nla_put_u32(ans_skb,
>>+                                         NLBL_CIPSOV4_A_MLSCATREM,
>>+                                         doi_def->map.std->cat.local[iter]);
>>+                     if (ret_val != 0)
>>+                             goto list_retry;
>>+                     nla_nest_end(ans_skb, nla_b);
>>+             }
>>+             nla_nest_end(ans_skb, nla_a);
>>+
>>+             break;
>>+     }
>>+     rcu_read_unlock();
> 
> What I meant in the previous posting is to put genlmsg_end() in here
> like the rest of the code to be clear and symmetric.

Okay, I put it there because it was a common trend in the code, i.e. end
the message then do a write, I thought I would combine them.  I'll split
it back out.

> The rest of the code has simliar issues, nevertheless this looks
> really great. Everything is extendable and relatively easy to
> maintain. This should definitely go into 2.6.19. Good work.

Thanks for your patience as I got the hang of the genetlink stuff.  I'll
make the changes you suggested and get a new version out soon.

-- 
paul moore
linux security @ hp
-
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to