echo into '/proc/filename' gives "Operation Not Permitted" error - linux

Platform: Ubuntu 5.15.0-43-generic.
I have written a loadable kernel module to create a file under /proc called testproc. The kernel module loads perfectly and created the /proc/testproc. The permissions on /proc/testproc are 0666 and owned by root. I am logged in as root for all operations.
I have implemented the read and write handler in my kernel module and they get called too.
When I run the command
echo "Hello" > /proc/testproc
the error seen is
bash: echo: write error: Operation not permitted
I am using the call
proc_create("testproc", 0666, NULL, &procfsFuncs)
to create the entry under /proc
Any pointers much appreciated.

I figured out my (trivial) mistake. I was expecting a non-zero result from copy_from_user(), when in reality copy_from_user returns 0 on success.

Related

Retrieve underlying file of tee command

References
Fullcode of what will be discussed here:
https://github.com/djon2003/com.cyberinternauts.linux.backup
activateLogs question that solved how to log to file and screen: https://stackoverflow.com/a/70792273/214898
Limitation
Just a small reminder from the last question: this script is executed on limited environment, on a QNAP (NAS).
Background
I have a function that activate logging which now has three modes: SCREEN, DISK, BOTH. With some help (from the question of the link above), I achieve to make work the BOTH option. DISK & BOTH use a file descriptor numbered 3. The first is pointing to a file and the second to stdout.
On exit of my script (using trap), it detects if there were logged errors and send them via email.
Code
function sendErrorMailOnExit()
{
## If errors happened, then send email
local isFileDescriptor3Exist=$(command 2>/dev/null >&3 && echo "Y")
if [ "$isFileDescriptor3Exist" = "Y" ]; then
local logFile=$(readlink /proc/self/fd/3 | sed s/.log$/.err/)
local logFileSize=$(stat -c %s "$logFile")
if [ $logFileSize -gt 0 ]; then
addLog "N" "Sending error email"
local logFileName=$(basename "$logFile")
local logFileContent=$(cat "$logFile")
sendMail "Y" "QNAP - Backup error" "Error happened on backup. See log file $logFileName\n\nLog error file content:\n$logFileContent"
fi
fi
}
trap sendErrorMailOnExit EXIT
Problem
As you can see, this works well because the file descriptor #3 is using a file. But now, using the BOTH option, the file descriptor #3 is pointing to stdout and the file is written via tee. Hence my question, how could I get the location of the file of tee.
Why not only using a variable coming from my function activateLogs would you say? Because, this function relaunches the script to be able to get all the logs not caught before the function is called. Thus why using this method to retrieve the error file location.
Possible solutions, but not the best (I hope)
One way would be to pass the file location through a script
parameter, but I would prefer not do that if that can be avoid.
Another, would be to create a "fake" file descriptor #4 (probably my best solution up to now) that would always point to the file.
Does anyone have an idea?
I finally opted for the creation of a "fake" file descriptor #4 that does not nothing except pointing to the current log file.

bpftrace: uprobe target file does not exist or is not executable

I want to use bpftrace to trace functions inside libasan library, which is inside /usr/lib/x86_64-linux-gnu/.
However
sudo bpftrace -e 'uretprobe:/usr/lib/x86_64-linux-gnu/libasan.so.4: __interceptor_malloc { printf("pid: %d, malloc %p\n", pid, retval); }'
gives error: uprobe target file '/usr/lib/x86_64-linux-gnu/libasan.so.4' does not exist or is not executable
I have tried: export LD_LIBRARY_PATH="/lib:/usr/lib:/usr/local/lib" but it does not help.
How can make the library executable for bpftrace? I need it to trace allocations done in a Firefox process. Thanks!
EDIT: I just found out that the permission on libasan is -rw-r--r--, which means it is indeed not executable. How should I make it executable?
I fixed it by doing chmod +x libasan.so.4.0.0

Fortran OPEN-call differs on NFSv3 vs NFSv4

I'm trying to understand the difference between why you can do an OPEN-call in fortran on NFSv3 in read-write mode on a file that you only have read-permissions on, while if you do the same thing on NFSv4 the OPEN-call will fail.
Let me explain, below is a simple fortran-program that opens given file (argument to the program) in read-write mode,
PROGRAM test_open
IMPLICIT NONE
! Parameters
INTEGER, PARAMETER :: lunin = 10
CHARACTER(LEN=100) :: fname
! Local
INTEGER :: i,ierr,siteid,nstation
REAL :: lat, lon, asl
CHARACTER(len=15) :: name
!----------------------------------------------------------------
!
! Open input file
!
CALL getarg(1,fname)
OPEN(lunin,file=fname,STATUS='OLD',IOSTAT=ierr)
IF ( ierr /= 0 ) THEN
WRITE(6,*)'Could not open ',TRIM(fname),ierr
STOP
ENDIF
WRITE(6,*)'Opened OK'
CLOSE(lunin)
END PROGRAM test_open
Save the above in test_open.f90 and compile with,
gfortran -o fortran test_open.f90
Now, execute the following on a mountpoint with NFSv3,
strace -eopen ./fortran file-with-only-read-permissions
And you should see the following lines (along with a lot of other output),
> open("file-with-only-read-permissions", O_RDWR) = -1 EACCES (Permission denied)
> open("file-with-only-read-permissions", O_RDONLY) = 3
So, we can clearly see that we get an "EACCES (Permission denied)" while trying to open in 'O_RDWR' (open read-write), but right after we see another open O_RDONLY (open read-only) and that succeeds.
Run the same program on a file on a NFSv4 share, and we get the following,
strace -eopen ./fortran file-with-only-read-permissions-on-nfsv4-share
> open("file-with-only-read-permissions-on-nfsv4-share", O_RDWR) = -1 EPERM (Operation not permitted)
So, here we get an "EPERM (Operation not permitted)" while trying to open the file in 'O_RDWR' (open read-write) and nothing more (ie application fails).
Doing the same tests in C with a small test-program it will fail to open the file in both scenarios (that is, it will not try to open the file in 'read-only-mode' after getting the "EACCES" on NFSv3).
So to the questions,
I assume the above behaviour is due to the implementation of the OPEN-call in fortran, and that if fortran gets an "EACCES (Permission denied)" while trying to open a file, it will automatically try to open the file in read-only (O_RDONLY). Is this assumption correct ?
I also assume that fortran doesn't have this "fallback-method" when getting an "EPERM (Operation not permitted)" while trying to open a file. Is this assumption correct, or am I missing something ?
C doesn't seem to implement a "fallback-method" in either a "EACCES" nor "EPERM". This seems correct to me, since this doesn't leave any room for confusion. If you try to open a file in a way that you do not have the permissions to do, the program should fail - my opinion.
I am aware of that there is a distinct difference between "Permission denied" and "Operation not permitted". And I guess that when mounting NFSv4 over kerberos there is a reason for getting "Permission denied" instead of "Operation not permitted", however some clarification regarding this area would be great.
Of course, adding the appropriate flags to the open-call (ACTION=READ) solves the problem. I'm just curios about my assumptions and if they are correct.
To answer your question, in order:
You are correct that gfortran will try to reopen a file in read-only mode when EACCES (or EROFS) is encountered.
You are also correct that EPERM is not handled this way, it is not mentioned in the libgfortran source tree at all.
As you say, this is a matter of opinion. Gfortran made the decision to do this a long time ago, and it seems to suit the users just fine.
I do not understand why NFS v4 returns EPERM in such a case. This seems at odds at least with the documentation in the open(2) Linux manpage that I have access to, where it is only mentioned when O_NOATIME has been specified (which libgfortran does not do). At least, this behavior does not seem to be portable.

Fortran 90 create directory syntax error

I thought I found out how to create directories in this post
Creating directory with name containing real number in FORTRAN
But when I tried to create a directory in my Fortran 90 program
call system('mkdir -p out/test')
or
call system('mkdir out/test')
I don't get any compilation errors or warnings, but I get the following runtime error:
The syntax of the command is incorrect.
Any idea what is wrong? Any help is greatly appreciated!
From the error message I assume you are using Windows. Then, you have to use \ as a folder separator:
call system('mkdir out\test')
Also, -p (the Unix option to create parent folders) is invalid for Windows (and also not required).

Mounting proc in non-privileged namespace sandbox

I'm trying to make a sandboxed environment using Linux namespaces. I've found a neat example at https://github.com/swetland/mkbox that roughly does what I want, but I'd like a credible /proc to appear inside the sandbox. How can I do that?
I tried bind mounting the proc FS on "proc", but that fails with EINVAL. When I try to mount "proc" normally, it yields EPERM.
ideas?
A local guru figured this out for me: the proc must use the (undocumented?) MS_REC flag, like so:
ok(mount, "/proc", "proc", NULL, MS_REC|MS_BIND, NULL);
the bind mount only does something useful if CLONE_PIDNS is not set, obviously.
I didn't look closely enough at your commit to know for sure if this is your issue, but EPERM will happen if you have CLONE_NEWUSER | CLONE_NEWNS but not CLONE_NEWPID. This is because in order to mount proc, you need CAP_SYS_ADMIN in the user namespace corresponding to the current PID namespace, not the current user namespace.
Linux 4.4, fs/proc/root.c, lines 112–117:
ns = task_active_pid_ns(current);
options = data;
/* Does the mounter have privilege over the pid namespace? */
if (!ns_capable(ns->user_ns, CAP_SYS_ADMIN))
return ERR_PTR(-EPERM);

Resources