Skip to content

Instantly share code, notes, and snippets.

@devnexen
Last active May 18, 2017 18:00
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save devnexen/232f4de03beddf09b4e93619d44ed8bc to your computer and use it in GitHub Desktop.
Save devnexen/232f4de03beddf09b4e93619d44ed8bc to your computer and use it in GitHub Desktop.
Blocking writing to a file descriptor
#include <sys/prctl.h>
#include <seccomp.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int
main(int argc, char *argv[])
{
ssize_t sz;
char buf[1] = { 0 };
int fd = open("/tmp/foobar", O_RDWR | O_CREAT);
// SECCOMP works per system call
scmp_filter_ctx ctx = seccomp_init(SCMP_ACT_ERRNO(EPERM));
seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(rt_sigreturn), 0);
seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(read), 0);
// We could have allowed write in general by setting the 4th parameter to 0
seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(write), 1, SCMP_A0(SCMP_CMP_EQ, STDOUT_FILENO));
seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(write), 1, SCMP_A0(SCMP_CMP_EQ, STDERR_FILENO));
seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(close), 0);
seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(exit), 0);
seccomp_load(ctx);
printf("read attempt\n");
sz = read(fd, buf, sizeof(buf));
if (sz < 0) {
fprintf(stderr, "read failed %s\n", strerror(errno));
goto end;
}
printf("read succesful\n");
buf[0] = 'a';
sz = write(fd, buf, sizeof(buf));
if (errno) {
fprintf(stderr, "expected write failure %s\n", strerror(errno));
goto end;
}
end:
// Any attempt to add a new privilege fails since the context has been loaded
if (seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(write), 0) != -1) {
fprintf(stderr, "expected expanding privileges failed\n");
} else {
printf("expanding privilege fails %s\n", strerror(errno));
}
seccomp_release(ctx);
close(fd);
return (0);
}
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>
#include <sys/stat.h>
int main(int argc, char *argv[])
{
int fd = open("/tmp/foobar", O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);
char buf[1] = { 0 };
ssize_t sz;
// Problem, lack of granularity since stdio includes both read and write ...
if (pledge("stdio", NULL) == -1) {
fprintf(stderr, "pledge failed %s\n", strerror(errno));
exit(-1);
}
sz = read(fd, buf, sizeof(buf));
if (sz < 0) {
fprintf(stderr, "read failed %zu, %s\n", sz, strerror(errno));
exit(-1);
}
printf("read succesful\n");
buf[0] = 'a';
sz = write(fd, buf, sizeof(buf));
// ... leads to have succesful write call
if (sz > 0) {
fprintf(stderr, "write should have failed\n");
goto end;
}
printf("write had failed as expected %s\n", strerror(errno));
end:
// But as always you cannot expand the privileges ...
if (pledge("stdio unix", NULL) != -1) {
fprintf(stderr, "pledge should have failed\n");
} else {
printf("pledge had failed as expected %s\n", strerror(errno));
}
printf("closing\n");
close(fd);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment