Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix #166: transition to standard skb linkage inside TempstaFW. #1000

Merged
merged 10 commits into from
Apr 14, 2018

Conversation

aleksostapenko
Copy link
Contributor

No description provided.

Copy link
Contributor

@krizhanovsky krizhanovsky left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The changes required by #166 are much deeper than implemented in the PR.

@@ -1,5 +1,5 @@
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please remove the patch from the master and generate a new patch from https://github.com/tempesta-tech/linux-4.14.32-tfw .

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

nskb->prev = skb;
skb->next = nskb;
if (nskb->next)
nskb->next->prev = nskb;
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The function must be removed since it does just the same as standard list_add() except it breaks the standard list behaviour using NULL as a tail pointer. The point of #166 is that our internal skb lists mut be the same as in the kernel.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Our current internal implementation is based and largely tied with NULL-terminated lists, so we cannot use full circular lists without significant redesign of code which work with our internal skb queue.

@@ -253,11 +250,11 @@ __skb_insert_after(struct sk_buff *skb, struct sk_buff *nskb)
static inline void
__skb_skblist_fixup(SsSkbList *skb_list)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe we can and should remove SsSkbList now. Regarding __skb_skblist_fixup() the only place where we use it is skb_fragment() and it seems that we used the function just because we had no circular list, so the function seems also must be removed.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SsSkbList is replaced with simple struct sk_buff *skb_head pointer to NULL-terminated list with additional tail pointer (skb_head->prev).

@@ -236,14 +236,11 @@ __it_next_data(struct sk_buff *skb, int i, TfwStr *it)
static inline void
__skb_insert_after(struct sk_buff *skb, struct sk_buff *nskb)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe all our own list stuff like ss_skb_queue_head_init(), ss_skb_queue_empty(), ss_skb_queue_tail() and so on must be removed now.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Functions ss_skb_queue_head_init(), ss_skb_queue_empty(), ss_skb_next(), ss_skb_peek() had been removed.


skb->next = skb_shinfo(skb)->frag_list;
list->first = list->last = skb;
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, skb_shinfo(skb)->frag_list is just a pointer to skb - the proof that we don't need SsSkbList any more. Since the function will work just with plain skb pointers, just 2 lines in size and is used only once, there is no need to keep the function and the code can be directly mode to ss_skb_unroll().

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

SsSkbCb *scb = TFW_SKB_CB(skb);
skb->prev = list->last;
list->last = skb;
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The same as above for ss_skb_init_from_frag_list().

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

}

static inline struct sk_buff *
ss_skb_next(struct sk_buff *skb)
{
return TFW_SKB_CB(skb)->next;
return skb->next;
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These changes and at the below (ss_skb_next(), ss_skb_peek_tail() and so on) - please remove the stuff and use standard skbuff and list API.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some functions had been removed (#1000 (comment)) but we cannot remove all our skb list API, as standard kernel skbuff list API is not applicable for our internal skb queue.

Copy link
Contributor

@krizhanovsky krizhanovsky left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The patch is much better, but the list design is till inconsistent. At least very strong motivation is requred to leave with the list in current state.

WARN_ON_ONCE(TFW_SKB_CB(skb_list->last)->next);
if (last->next)
skb_head->prev = last->next;
WARN_ON_ONCE(skb_head->prev->next);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I still don't see the reason for the function and why can't we move to double linked list if we need last pointer or accurate NULL terminated list like skb->frag_list: current prev meaning the last item as well as double linked list with NULLs for the last and first items look ugly and error prone.

Copy link
Contributor

@vankoven vankoven left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have nothing to add to @krizhanovsky review. It's odd to have null-terminated double-linked list. Using only one well-known approach is less error-prone.

Copy link
Contributor

@krizhanovsky krizhanovsky left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The lists look good for me. Please make the minor cleanups and necessary changes to compile for 4.14.

if (!*skb_head) {
WARN_ON_ONCE(1);
return 0;
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Better to write as

if (WARN_ON_ONCE(!*skb_head))
    return 0;

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Corrected.

if (last->next)
skb_head->prev = last->next;
WARN_ON_ONCE(skb_head->prev->next);
nskb->next->prev = nskb->prev->next = nskb;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bit simplier

nskb->next->prev = skb->next = nskb;

Also comment "Note that the list's pointer to the last item is not updated here.has no sense any more and should be removed. Also it's worh mentioning whyskb_insert()` doens't suite our need and we need our own function.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Corrected.

if (*skb_head == skb)
*skb_head = skb->next;
else
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

*skb_head == skb should be in the else branch - there is no sense to make the check after *skb_head = NULL

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Corrected.

Copy link
Contributor

@krizhanovsky krizhanovsky left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good to merge after probably the one small fix.

@@ -298,7 +300,8 @@ tfw_filter_stop(void)
if (tfw_runstate_is_reconfig())
return;
if (ip_filter_db) {
nf_unregister_hooks(tfw_nf_ops, ARRAY_SIZE(tfw_nf_ops));
nf_unregister_net_hooks(&init_net, tfw_nf_ops,
ARRAY_SIZE(tfw_nf_ops));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why init_net and why don't you add the hooks to all network namespaces as other security modules do this using register_pernet_subsys()?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Corrected.

Copy link
Contributor

@vankoven vankoven left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good to merge after small fixes.

@@ -1612,8 +1612,8 @@ tfw_cfg_read_file(const char *path, size_t *file_size)
do {
TFW_DBG3("read by offset: %d\n", (int)offset);
read_size = min((size_t)(buf_size - offset), PAGE_SIZE);
bytes_read = vfs_read(fp, out_buf + offset, read_size, \
&offset);
bytes_read = kernel_read(fp, out_buf + offset, read_size, \
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Backslash is not required here and can be removed.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Corrected.

@@ -341,7 +341,7 @@ static struct ctl_table tfw_sysctl_tbl[] = {
.mode = 0644,
.proc_handler = tfw_ctlfn_state_io,
},
{ 0 }
{}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Although GCC complies the code, the statement is valid for C++ and prohibited for C. { 0 } is more correct for C.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In context of introducing structure randomization functionality into the kernel, various structures (including struct ctl_table) had been marked with __randomize_layout (torvalds/linux@3859a27#diff-9ad17f888d19adc0b5148b288e553b9b) which implies designated_init GCC attribute, which in turn means that initialization of structures declared with this attribute must use designated initializers rather than positional initializers. Also -Werror=designated-init compiler option had been introduced into kernel makefile (torvalds/linux@c834f0e). So when struct ctl_table initialized with
{ 0 }, GCC produces an error, since it recognizes this type of initialization as positional partial initialization (not the designated initialization).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants