-
Notifications
You must be signed in to change notification settings - Fork 173
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
RFE: add transaction support to the libseccomp API #415
base: main
Are you sure you want to change the base?
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the patchset, @pcmoore. I think the user-facing API is good. I do have a few questions here and there but nothing earth shattering.
@@ -2559,8 +2566,9 @@ void db_col_transaction_commit(struct db_filter_col *col) | |||
if (snap->shadow) { | |||
/* leave the shadow intact, but drop the next snapshot */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this block of code accessible? I hacked around for just a bit and was unable to hit it.
snap->shadow
is effectively always set to false
at the start of db_col_transaction_start()
. snap->shadow
is only set true
at the end of db_col_transaction_commit()
- approximately 100 lines after this. Is there a code path where snap->shadow
is true
at this point?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unfortunately, it looks like I never responded back when I "fixed" this, so I'm sorta going by memory/comments/self-code-review and I believe the answer that yes, you can hit this code when you start nesting transactions.
_db_snap_release(snap->next); | ||
struct db_filter_snap *tmp = snap->next; | ||
snap->next = tmp->next; | ||
_db_snap_release(tmp); | ||
} | ||
return; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(This comment is for a couple lines down, but Github won't let me comment there. Specifically this line: https://github.com/pcmoore/misc-libseccomp/blob/working-transactions/src/db.c#L2589)
Since we had issues handling aborts, I wrote a quick test for this large block of code where the col's filter count didn't match the snap's filter count.
Here's the test I threw together:
drakenclimber@3814774
And here's the code coverage (prior to this test these lines weren't being hit):
https://coveralls.io/builds/62918086/source?filename=src%2Fdb.c#L2589
Interestingly this leads to a valgrind failure, but I haven't looked into it yet.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the test! I've included it in my dev branch (which I'm going to refresh here in a few minutes) and used it to fix a number of bugs.
into the kernel can not be modified, only new seccomp filters can be added on | ||
top of the existing loaded filter stack. | ||
.P | ||
Finishing, or committing, a transaction is optional, although it is encouraged. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like this code block as it clearly explains why a user would be interested in this feature
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As you have outlined in issue #181, this should greatly help in testing transactions 👍. Do you have a use case in mind for libseccomp's users (like systemd, etc.)?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No one particular use case in mind, I'll leave that up to more clever people than I :)
* This function rejects the current seccomp filter transaction. | ||
* | ||
*/ | ||
void seccomp_transaction_reject(const scmp_filter_ctx ctx); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would we ever want a return value here? I can't think of one, but as you mentioned in the cover letter, the API is set in stone once we release this :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm struggling to think of one too, what do you think, should we return an int?
@@ -145,6 +145,7 @@ struct db_filter_snap { | |||
struct db_filter **filters; | |||
unsigned int filter_cnt; | |||
bool shadow; | |||
bool user; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm thinking a bool
should meet our needs initially, but I'm wondering if long-term we'll want to switch to a transaction number (with a special bit for user-initiated transactions). I'm afraid the bool
check of if snap->user != user
may not be powerful enough someday.
The good thing is none of this exposed by the API, so we could change it later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agree, let's leave it as a bool now, mostly for simplicity; we can change it later if needed.
Valgrind output of the test I added:
|
Well unsurprisingly these are the lines that valgrind is angry about:
|
As expected, resizing the snap filter array appeases valgrind. I feel like it's a worthwhile change since this is likely an infrequent operation (and perhaps only in an error path). I think proper memory management may outweigh speed in this case. Also, I don't claim to like my implementation - it was just a proof of concept to verify the root cause :).
|
6adf397
to
a3a7056
Compare
283f792
to
0deb5a2
Compare
I have a rough schedule the next few days, but I should have time at the end of the week to check this (and the other libseccomp patches) out later in the week. |
Hi Tom, no immediate rush, but when you have the time it would be great to look over the other PRs; if you don't have time to merge them - assuming they look good to you - just leave your ACK and I'll take care of them. As far as this PR is concerned, don't spend your time reviewing it just yet, I want to finish up a few things and make sure everything looks good on my end first; I'll leave a note when it is ready for review. Thanks for the previous review and feedback, it's been very helpful. |
Sounds good. I'll focus on the other PRs this week. Let me know when this one is ready, and I'll start looking at it again. |
@pcmoore, I admit I haven't paid attention to this pull request lately. Do you want me to review, or are you still adding some more changes? Thanks! |
I still need to give it a once over, but thanks for checking :) |
It turns out we don't properly handle transaction aborts as we should, this likely broke when we implemented the shadow snapshots but as the transaction concept was not exported via the API, and callers most likely abandoned the filter on error this went unnoticed. This patch ensures that transaction aborts are handled properly by correctly managing the filter's transaction stack. Signed-off-by: Paul Moore <[email protected]>
Fix an off-by-one error that was causing us to leak a db_filter struct at transaction commit time when we removed an arch/ABI in a transaction. Reported-by: Tom Hromatka <[email protected]> Signed-off-by: Paul Moore <[email protected]>
While libseccomp has internally has transaction support for some time now, it hasn't been accessible to callers through the libseccomp API. This patch adds a transaction API as well as supporting documentation and a new unit regression test. int seccomp_transaction_start(const scmp_filter_ctx ctx) int seccomp_transaction_commit(const scmp_filter_ctx ctx) void seccomp_transaction_reject(const scmp_filter_ctx ctx) Signed-off-by: Paul Moore <[email protected]>
Add a test to verify the logic at the end of db_col_transaction_commit() properly copies and releases the snapshots from the filter when the filter length doesn't match the snapshot length. Signed-off-by: Tom Hromatka <[email protected]> [PM: subj tweak] Signed-off-by: Paul Moore <[email protected]>
0deb5a2
to
893e70d
Compare
Okay @drakenclimber, I think this is ready for a closer review when you have the time. |
This PR contains two patches, the first fixes an existing problem with transaction management and the second adds a new transaction API to libseccomp.
@drakenclimber when you have the chance please take a look and let me know what you think, especially regarding the API as that is difficult/impossible to change later. If everything looks okay, I'll submit another PR with the "src/db.c" fix for the release-2.5 branch,