Interesting to see you "play" with the functionality you just implemented at the end, think it's a good sign when you get non trivial/non-intuitive results ("oh of course this process needs access to x, y and z"). Kinda transcends what you expected and makes you truly understand stuff. Like not only does pledge acts as a protection but it's also a contract declaring what you are going to consume, not only a safeguard for security but also resource consumption or more, a sanity check etc.
Hey MGA! Yeah it’s really interesting how much your understanding of a system can improve when you get a new tool to poke at it with :) We should always remember to experiment with new tools every now and then for this reason!
I’m today’s episode of 👏 Security 👏 Month, a love story straight from a soap opera: “Don’t worry, pledge! I’ll make space for you, even if it takes a while...” _A solid 5/7_ ~ IGN _A beautiful masterpiece_ ~ The Simon
wth is this channel and why the f am i only just finding it now!? THIS is what ive wanted on a linux channel for years, straight up dope need more people going through common programs showing us what we can do and showing man page entries the general process fom a coding side! its this sorta thing that my brain has never understood. like i can write a little cpp and a little python maybe js using node but i havent ever gotten anything from a manpage cause my adhd just goes "wtf am i supposed to read or take from this mass of text!?" thank you for the channel i am now addicted!
Instead of checking the pledges for every syscall, do you think it would be possible to patch the syscall table for the process to remove all calls that are not allowed after the pledge?
This is super interesting! Makes me wonder, though - what do you think about the idea of having a C++ api for syscalls etc for the userland, which would be nicer to use than C-style calls? You know, using AK::Strings, enum classes, etc. So a call to, say, int pledge(const char*, const char*) becomes something like Result pledge(PledgeMask, PledgeMask) or whatever. I feel like that's an interesting idea to think about (although maybe too much for the current scope and too much work for the little bit of "niceness" it would add), but would enforce a lot just through the typesystem alone! Something like that would move problems like straight up invalid strings or other invalid things into the userspace, as a responsibility of the callee. I'm aware it's just a geeky idea that isn't very practical, but in general, do you have any thoughts on this?
You can't give responsibility for invalid arguments to userspace, because even if the C++ typesystem enforces correctness, you could always write a program in any other programming language (such as C), that would send arbitrary instructions to the syscall.
While watching I was wondering, in your macros you write do { ... } while(0). Is there a difference between that and instead writing { ... }, where the latter makes a local scope? Or is there some other reason that I don’t see also?
Forgotten Mohawks Writing “do { } while (0)” is a safeguard against having someone do something like this: #define DO_THING(x) { ... } int main(int argc, char** argv) { ... while (bool) DO_THING(thing) // lmaoooo }
The reason is so that you can do f(x); with macros and it looks consistent with functions: stackoverflow.com/questions/1067226/c-multi-line-macro-do-while0-vs-scope-block
@@awesomekling pledge is certainly less complicated. IMO seccomp with EBPF is very very powerful but should be wrapped in a pledge like function to make it easier to use in your average apps.
Right, the main difference being that seccomp is too complicated for 99.9% of programs to bother using it and this is so dang simple that anyone can apply it to their code :) Or at least that’s my feeling based on looking at some examples of seccomp.
Adding things to a pledge would eliminate the entire point. A lot of that syscall could probably be put into a method you call twice with a couple pointers. Edit: VALIDATE_PROMISE perhaps? Edit: Might be interesting if you could mark a page as superuser when it's used in a syscall then copy it if userspace assessees it. Might be able to eliminate a bunch of attacks and might not have too much overhead.
Never heard of pledge, what a crappy idea. It would be better if the compiler where modified to inspect the calls made by the binary and build some sort of mask that was handed to the kernel rather than relying on the user to specify it manually in the source ......
That defeats the whole purpose IMO because it's supposed to be a safeguard for the user against themselves. One of the reasons of using pledge() is helping yourself limit what your program does
@@i.donthaveanameanymore I do not agree. The program does whatever it is coded to do, whatever that is, adding some form of coarse grained permissions on top is pointless. An automated system could be more fine grained and less subject to bit rot. Personally I think the whole idea of pledge() is poor at best, it seems more a crude hack rather than any true solution to security issues. If the kernel allows buffer overruns to inject code that can be executed then that seems a failure of kernel design or stack management rather than something the programmer should be directly concerned with.
@@jonshouse1 Who says the kernel allows buffer overflows? What does that have to do with pledge? The idea is that you can limit your programs, so if you really are only doing I/O you can tell the OS to restrict you to that. Not only do you protect yourself from accidentally allowing the user to do more with arbitrary code execution, but you also can make sure you don't accidentally use any more syscalls that would make your program run closer to the OS. You can make sure your program is doing exactly what you want it to do. It's not meant to be a catch all for security, but it's one of many features that can help
Interesting to see you "play" with the functionality you just implemented at the end, think it's a good sign when you get non trivial/non-intuitive results ("oh of course this process needs access to x, y and z"). Kinda transcends what you expected and makes you truly understand stuff. Like not only does pledge acts as a protection but it's also a contract declaring what you are going to consume, not only a safeguard for security but also resource consumption or more, a sanity check etc.
Hey MGA! Yeah it’s really interesting how much your understanding of a system can improve when you get a new tool to poke at it with :)
We should always remember to experiment with new tools every now and then for this reason!
Andreas, thank you so much for your videos. Big fan
Hey Joshua! I’m glad you like the content :)
I’m today’s episode of 👏 Security 👏 Month, a love story straight from a soap opera:
“Don’t worry, pledge! I’ll make space for you, even if it takes a while...”
_A solid 5/7_
~ IGN
_A beautiful masterpiece_
~ The Simon
wth is this channel and why the f am i only just finding it now!? THIS is what ive wanted on a linux channel for years, straight up dope need more people going through common programs showing us what we can do and showing man page entries the general process fom a coding side! its this sorta thing that my brain has never understood. like i can write a little cpp and a little python maybe js using node but i havent ever gotten anything from a manpage cause my adhd just goes "wtf am i supposed to read or take from this mass of text!?" thank you for the channel i am now addicted!
Nice, never heard of pledge before, I guess all this OS Hacking stuff got you there :o
Grand Master at work. I love it. Please continue.
Instead of checking the pledges for every syscall, do you think it would be possible to patch the syscall table for the process to remove all calls that are not allowed after the pledge?
This is super interesting! Makes me wonder, though - what do you think about the idea of having a C++ api for syscalls etc for the userland, which would be nicer to use than C-style calls? You know, using AK::Strings, enum classes, etc.
So a call to, say,
int pledge(const char*, const char*)
becomes something like
Result pledge(PledgeMask, PledgeMask)
or whatever.
I feel like that's an interesting idea to think about (although maybe too much for the current scope and too much work for the little bit of "niceness" it would add), but would enforce a lot just through the typesystem alone! Something like that would move problems like straight up invalid strings or other invalid things into the userspace, as a responsibility of the callee.
I'm aware it's just a geeky idea that isn't very practical, but in general, do you have any thoughts on this?
You can't give responsibility for invalid arguments to userspace, because even if the C++ typesystem enforces correctness, you could always write a program in any other programming language (such as C), that would send arbitrary instructions to the syscall.
BeOS used C++ APIs, and it became a problem, as it was impossible to upgrade the compiler without breaking every program.
Promises, and they still feel all so wasted on myself♬
And you keep pledging me.. pledging me that you’ll be sweet 🎶
lets share this one !
This is great. Thank you.
While watching I was wondering, in your macros you write do { ... } while(0). Is there a difference between that and instead writing { ... }, where the latter makes a local scope? Or is there some other reason that I don’t see also?
Forgotten Mohawks Writing “do { } while (0)” is a safeguard against having someone do something like this:
#define DO_THING(x) { ... }
int main(int argc, char** argv) {
...
while (bool) DO_THING(thing)
// lmaoooo
}
Simon Struthers thanks, makes sense :)
The reason is so that you can do f(x); with macros and it looks consistent with functions: stackoverflow.com/questions/1067226/c-multi-line-macro-do-while0-vs-scope-block
No seccomp? ;)
I looked at a bunch of examples of seccomp and felt that it was far too complicated, and this is just so dang simple anyone can use it :)
@@awesomekling pledge is certainly less complicated. IMO seccomp with EBPF is very very powerful but should be wrapped in a pledge like function to make it easier to use in your average apps.
This is kinda like seccomp I guess, neat :)
Right, the main difference being that seccomp is too complicated for 99.9% of programs to bother using it and this is so dang simple that anyone can apply it to their code :)
Or at least that’s my feeling based on looking at some examples of seccomp.
Oh yeah. Seccomp is way more complex, but it is also made way easier with libseccomp.
You shouldn't copy the worst syscalls. Use a bitmask, not a string.
Adding things to a pledge would eliminate the entire point.
A lot of that syscall could probably be put into a method you call twice with a couple pointers.
Edit:
VALIDATE_PROMISE perhaps?
Edit:
Might be interesting if you could mark a page as superuser when it's used in a syscall then copy it if userspace assessees it. Might be able to eliminate a bunch of attacks and might not have too much overhead.
Never heard of pledge, what a crappy idea. It would be better if the compiler where modified to inspect the calls made by the binary and build some sort of mask that was handed to the kernel rather than relying on the user to specify it manually in the source ......
That defeats the whole purpose IMO because it's supposed to be a safeguard for the user against themselves. One of the reasons of using pledge() is helping yourself limit what your program does
@@i.donthaveanameanymore I do not agree. The program does whatever it is coded to do, whatever that is, adding some form of coarse grained permissions on top is pointless. An automated system could be more fine grained and less subject to bit rot. Personally I think the whole idea of pledge() is poor at best, it seems more a crude hack rather than any true solution to security issues. If the kernel allows buffer overruns to inject code that can be executed then that seems a failure of kernel design or stack management rather than something the programmer should be directly concerned with.
@@jonshouse1 Who says the kernel allows buffer overflows? What does that have to do with pledge? The idea is that you can limit your programs, so if you really are only doing I/O you can tell the OS to restrict you to that. Not only do you protect yourself from accidentally allowing the user to do more with arbitrary code execution, but you also can make sure you don't accidentally use any more syscalls that would make your program run closer to the OS. You can make sure your program is doing exactly what you want it to do. It's not meant to be a catch all for security, but it's one of many features that can help