Is there a source code for /usr/bin/ulimit? I need to see a user's complete list of rlimit's without him being in a shell.
In this case, we have problems running memory-intensive programs from the web server (user wwwrun, usually having /bin/false as login shell in /etc/passwd), and we suspect some system-imposed limits are blocking it from completing these programs.
In former times, there has been a /usr/bin/ulimit binary, but these seem to be gone.
So what I'm looking for is a C implementation of the ulimit command (nowadays usually being only available as (ba)sh built-in). It doesn't need to have any "setrlimit" capabilities - just printing all limits would be sufficient. We'd then set this command as wwwrun's login shell and a "su - wwwrun" would show all rlimits this user has.
Thanks for any hints!
There cannot be any /usr/bin/ulimit (or /usr/bin/cd) executable, because the setrlimit(2) syscall operate on the current shell process (changing a property of the current process which will by default be inherited by further child processes, see fork(2) & execve(2)). So ulimit, like cd (which invokes the chdir(2) syscall), has to be a shell builtin
From inside your C program just call the setrlimit syscall. Don't forget to test for failure (and on failure display errno perhaps using perror or strerror). To query the current limits, use getrlimit(2) or read -within your program- sequentially the /proc/self/limits pseudo-file (see proc(5) for more, or /proc/1234/limits for process of pid 1234).
FILE* f = fopen("/proc/self/limits", "r");
if (f) {
char linbuf[128];
do {
memset (linbuf, 0, sizeof(linbuf));
fgets (linbuf, sizeof(linbuf), f);
fputs(linbuf, stderr);
} while (!feof(f));
fclose (f);
fflush(NULL);
} else perror("/proc/self/limits");
I also recommend reading Advanced Linux Programming and intro(2). See also Linux PAM and configuration files like /etc/security/limits.conf and under /etc/pam.d/
Thanks for the hints - I've set a simple text file cat-limits as login shell for wwwrun, simply containing one line with
#!/bin/cat /proc/self/limits
and that gave me what I want.
Cheers
Related
I am pretty new to linux kernel.I am trying to generate PWM through linux. The API man talks about a sysfs interface. I want to implement a userspace program in C. But using PWM forces me to use a command line. Furthermore, using read, write is a problem in C as when I am using cd, it is changing path directory.
Thus the path is variable. Is there any way I can pass values to pwm_config() without using sysfs? Perhaps through ioctl? If yes, then what would be the procedure?
Application C code:
void main(){
int export = open("/sys/class/pwm/pmwchip0/export",O_WRONLY);
int period,duty_cycle,enable;
if(export == -1)
{
perror("Export:");
}
and so on for other files like period and duty cycle.
When I try to run my application I get the following error.
Export:: No such file or directory
Export_write: Bad file descriptor
Period_write:: Bad file descriptor
Duty_cycle_write:: Bad file descriptor
Enable_write:: Bad file descriptor
As far as I know, the sysfs is the only standard userspace interface to PWM. But anything you can do from the command line can be done in C (the shell is written in C, after all).
The problem you are having with cd is not actually a problem. Inside sysfs the directories in /sys/class/pwd/* are actually symbolic links to the proper devices. In your case /sys/class/pwm/pwmchip0 is a symlink to /sys/devices/soc0/amba/f8001000.timer/pwm/pwmchip0.
The funny thing is that some shells, when you cd a symbolic link will resolve to the real directory, but other shells will actually keep the symlink name as the current directory.
But that issue with the directory symlinks should not be an issue for you. A C program willing to manage PWM devices should not change the working directory. Instead open the files with the full path:
open("/sys/class/pwm/pwmchip0/npwm", O_RDONLY);
and so on.
I want to exploit capabilities to run some tests with perf, without running commands as root and without tweaking /proc/sys/kernel/perf_event_paranoid. Some error messages of perf says:
You may not have permission to collect stats.
Consider tweaking /proc/sys/kernel/perf_event_paranoid,
which controls use of the performance events system by
unprivileged users (without CAP_SYS_ADMIN).
The current value is 2:
-1: Allow use of (almost) all events by all users
>= 0: Disallow raw tracepoint access by users without CAP_IPC_LOCK
>= 1: Disallow CPU event access by users without CAP_SYS_ADMIN
>= 2: Disallow kernel profiling by users without CAP_SYS_ADMIN
so i tried created some bash script with the same source but different sets of capabilities in the following way:
wrapper_no_cap.sh -> no capabilities set
wrapper_cap_ipc_lock.sh -> setcap cap_ipc_lock+eip ./wrapper_cap_ipc_lock.sh
wrapper_cap_sys_admin.sh -> setcap cap_sys_admin+eip ./wrapper_cap_sys_admin.sh
Every script has the same source, which is the following:
#!/bin/bash
perf stat -e L1-dcache-load-misses:k seq 1 10
But every script i run gives me the result as if i were a regular user (which means i cannot count kernel events or other privileged stuff). It's like capabilities are discarded when i call the script. perf version is 4.11.ga351e9.
What is wrong with this method?
Script files often have their suid bit disabled (both in kernel and in some shell interpreters), seems there is similar effect on capabilities (and script files are actually started using interpreters like bash ./scriptfile, so capabilities from the script file may not be inherited by the process):
https://unix.stackexchange.com/questions/364/allow-setuid-on-shell-scripts
https://unix.stackexchange.com/questions/87348/capabilities-for-a-script-on-linux
Use small simple compiled program to call perf with exec/execve and set capabilities on binary ELF.
Actual code in Linux kernel for script starting -
http://elixir.free-electrons.com/linux/v4.10/source/fs/binfmt_script.c - uses interpreter binary file, not the script file (old bprm->file), to get permissions like suid
/*
* OK, now restart the process with the interpreter's dentry.
*/
file = open_exec(interp);
if (IS_ERR(file))
return PTR_ERR(file);
bprm->file = file;
retval = prepare_binprm(bprm);
http://elixir.free-electrons.com/linux/v4.10/source/fs/exec.c#L1512
/*
* Fill the binprm structure from the inode.
* Check permissions, then read the first 128 (BINPRM_BUF_SIZE) bytes
*
* This may be called multiple times for binary chains (scripts for example).
*/
int prepare_binprm(struct linux_binprm *bprm)
{
int retval;
bprm_fill_uid(bprm);
/* fill in binprm security blob */
retval = security_bprm_set_creds(bprm);
if (retval)
return retval;
bprm->cred_prepared = 1;
...
static void bprm_fill_uid(struct linux_binprm *bprm)
{
/* Be careful if suid/sgid is set */
inode_lock(inode);
/* reload atomically mode/uid/gid now that lock held */
mode = inode->i_mode;
uid = inode->i_uid;
gid = inode->i_gid;
...
I figured out a turnaround taking advantage #osgx suggestion.
I wrote this small C program which wraps perf. Here it is:
#include <unistd.h>
#include <stdio.h>
#include <sys/capability.h>
#define MY_CAPABILIY "cap_sys_admin+eip"
int main(int argc, char * argv[], char * envp[])
{
cap_t old_cap=cap_get_proc(); //save current capabilities
//getting MY_CAPABILITY associated struct
cap_t csa = cap_from_text(MY_CAPABILIY);
//set capabilities
if(cap_set_proc(csa)<0) fprintf(stderr,"cannot set %s\n",MY_CAPABILIY);
execve("/usr/bin/perf",argv,envp); //exec perf
//restore capabilties
if(cap_set_proc(old_cap)<0) fprintf(stderr, "Error on capability restore\n" );
return 0;
}
Let's call the executable generated from the code above perf_wrapper. It is compiled with libcap (add the option -lcap to gcc). The executable simply set MY_CAPABILITY as the capability of the process and then runs perf (or other commands). But this is not sufficient to run perf with CAP_SYS_ADMIN because the executable of perf does not have any capability. To let the things work it is also required to add some capabilities to the perf executable.
The steps are the following:
sudo setcap cap_sys_admin+ei /usr/bin/perf , This sets perf capabilities of CAP_SYS_ADMIN to effective and inheritable (also setting permitted won't allow normal users to run perf without capabilities).
sudo setcap cap_sys_admin+eip perf_wrapperset the capability of perf_wrapper
Now it is possible to use perf with CAP_SYS_ADMIN by executing perf_wrapper and passing params just like perf in normal bash scripts.
NOTE: i am not an expert of capabilities. I hope that i didn't do big security mistakes.
Not sure if this is the right place to ask.
Say I write a shell that takes stdin input, filters this input so let's say only certain commands like
ls (list contents of binary directory and subdirectory)
update (git clone)
build (go build)
test (go test)
start (systemctl start this.service only)
stop (systemctl stop this.service only)
running (is the binary being executed and with how many GOMAXPROCS?)
usage (memory, cpu usage)
gensvc (generate .service file)
exit (leave shell/logout)
work, you guessed it, I'm trying to give a user only very limited maintenance access over ssh.
Say I'm careful with \0 (I'd write it in Go anyway using bufio.Scanner)
Is there any way to stop the running shell and execute /bin/sh or similar or any way to get around this shell?
The idea is a user should push their stuff via git to a bare repo, this repo is cloned to the filesystem to a certain directory, then go build is called and the binary is ran with a systemd .service file that is generated previously.
Thinking logically, if the user is only able to write certain strings that are accepted, no there is no way. But maybe you know of one, some ctrl+z witchcraft ;) or whatever.
The only attack surface is the input string or rather bytes. Of course the user could git push a program that builds its own shell or runs certain commands, but that's out of scope (I would remove capabilities with systemd and restrict device access and forbid anything but the connection to the database server, private tmp and all, namespace and subnamespace it TODO)
The only problem I see is git pushing but I'm sure I could work around that in a git only mode argv and adding it to ~/.ssh/authorized_keys. something like lish gitmode and execute stdin commands if they start with git or something like it.
Example:
https://gist.github.com/dalu/ce2ef43a2ef5c390a819
If you're only allowed certain commands, your "shell" will read the command, parse it and then execute it then you should be fine, unless I misunderstood it.
Go "memory" can't be executed, not without you doing some nasty hacks with assembly anyway, so you don't have to worry about shell injection.
Something along these lines should be safe:
func getAction() (name string, args []string) {
// read stdin to get the command of the user
}
func doAction() {
for {
action, args := getAction()
switch action {
case "update": //let's assume the full command is: update https://repo/path.git
if len(args) != 1 {
//error
}
out, err := exec.Command("/usr/bin/git", "clone", "--recursive", args[0]).CombinedOutput()
// do stuff with out and err
}
}
}
If you are implementing the shell yourself and directly executing the commands via exec() or implementing them internally, then it is certainly possible to produce a secure restricted shell. If you are just superficially checking a command line before passing it on to a real shell then there will probably be edge cases you might not expect.
With that said, I'd be a bit concerned about the test command you've listed. Is it intended to run the test suite of a Go package the user uploads? If so, I wouldn't even try to exploit the restricted shell if I was an attacker: I'd simply upload a package with tests that perform the actions I want. The same could be said for build/start.
Have it reviewed by a pentesting team.
People can be very creative when breaking out a sandbox of any type. Only if you never accept the user's input you can consider yourself rather safe on premises (but here any command is an input) - paper security assumptions are considered a weak to assess the software. They are similar to 'no-bug' assumptions for an algorithm on paper: as soon as you implement it, 99% of time a bug raises
If I've got a handle to an open file, is it possible to create a hard link to that file after all references to it have been removed from the filesystem?
For example, something like this:
fd = fopen("/tmp/foo", "w");
unlink("/tmp/foo");
fwrite(fd, "Hello, world!\n");
create_link_from_fd(fd, "/tmp/hello");
fclose(fd);
Specifically, I'd like to do this so that I can safely write to large data files, then move them into place atomically without having to worry about cleaning up after myself if my program is killed in the middle of writing the file.
The newly released linux 3.11 offers a solution to this problem with the new O_TMPFILE open(2) flag. With this flag you can create an "invisible" file (i.e. an inode with no hardlinks) in some file system (specified by a directory in that file system). Then, after the file is fully set up, you can create a hardlink using linkat. It works like this:
fd = open("/tmp", O_TMPFILE | O_RDWR, 0600);
// write something to the file here
// fchown()/fchmod() it
linkat(fd, "", AT_FDCWD, "/tmp/test", AT_EMPTY_PATH);
Note that aside from the >=3.11 kernel requirement, this also requires support from the underlying file system (I tried the above snippet on ext3 and it worked, but it did not seem to work on btrfs).
Not generally, no. [Edit: since Linux 3.11 there is now linkat; see safsaf32's answer. This does not work on POSIX systems in general since POSIX linkat is restricted to directories only.] There are security considerations here: someone can pass to you an open file descriptor that you could not normally open on your own, e.g.:
mkdir lock; chmod 700 lock
echo secret contents > lock/in
sudoish cmd < lock/in
Here cmd runs as a user who has no permission to open the input file (lock/in) by name, but can still read from it. If cmd could create a new name on the same file system, it could pass the file contents on to a later process. (Obviously it can copy those contents, so this issue is more of a "pass the contents on by mistake" thing than "pass the contents on, on purpose".)
That said, people have come up with ways of "relinking" files by inode/vnode internally (it's pretty easy to do inside most file systems), so you could make your own private system call for it. The descriptor must refer to a real file on the appropriate mount point, of course—there's no way of "relinking" a pipe or socket or device into becoming a regular file.
Otherwise you're stuck with "catch signals and clean up and hope for the best", or a similar trick, "fork off a subprocess, run it, and if it succeeds/fails, take appropriate move/clean-up action".
Edit to add historical note: the above lock example is not particularly good, but back in the days of V6 Unix, MDQS used a fancier version of this trick. Bits and pieces of MDQS survive in various forms today.
On Linux, you might try the unportable trick of using /proc/self/fd by trying to call
char pbuf[64];
snprintf (pbuf, sizeof(pbuf), "/proc/self/fd/%d", fd);
link(pbuf, "/tmp/hello");
I would be surprised if that trick worked after an unlink("/tmp/foo") ... I did not try that.
A more portable (but less robust) way would be to generate a "unique temporary path" perhaps like
int p = (int) getpid();
int t = (int) time(0);
int r = (int) random();
sprintf(pbuf, sizeof(pbuf), "/tmp/out-p%d-r%d-t%d.tmp", p, r, t);
int fd = open (pbuf, O_CREAT|O_WRONLY);
Once the file has been written and closed, you rename(2) it to some more sensible path. You could use atexit in your program to do the renaming (or the removing).
And have some cron job to clean the [old] /tmp/out*.tmp every hour...
hi all:
recently i'm working on make checkpoint on linux process and encountered a problem,it looks like that when i munmap memory map of the executable to current process,the symlink /proc/self/exe is dead.what i want is to make this symlink pointing to a other executable(the one for my resumed processs),is that possible?i tried delete it and recreate, permission denied. english is not my native language, i hope i've made my point,thanx
prctl(PR_SET_MM_EXE_FILE, ...)
Supersede the /proc/pid/exe symbolic link with a new one pointing to a new executable file identified by the file descriptor provided in arg3 argument. The file descriptor should be obtained with a regular open(2) call.
No. /proc is completely managed by the kernel and does not allow changes like that.
But you may be able to start a new process (with fork() perhaps) and map your memory snapshot into that.