mount failed, errno is 20? - linux

I'm newbie in linux program. why following code failed? its output is "failed 20".
but in terminal the command: sudo mount /dev/sdb /home/abc/work/tmp works.
void main()
{
int rtn;
rtn=mount("/dev/sdb","/home/abc/work/tmp","vfat",MS_BIND,"");
if (rtn==-1)
printf("failed %d.\n",errno);
else
printf("OK!\n");
}

You can't bind-mount a device, only a directory. Try providing a useful value for mountflags.

Error 20 is ENOTDIR (http://www-numi.fnal.gov/offline_software/srt_public_context/WebDocs/Errors/unix_system_errors.html).
I think with MS_BIND, you would need the first argument to be an actual directory somewhere, not a device. See also the man page for mount
What you are trying to do would be equivalent to sudo mount --bind /dev/sdb /home/abc/work/temp which will give you an error too.

You should print out not just the errno value, but also the corresponding error message:
printf("failed %d: %s\n", errno, strerror(errno));
This should reveal the reason for the problem. ("Not a directory", so /home/abc/work/tmp does not seem to be a directory.)
(There are various other problems with your code, such as missing #include statements, and writing error messages to stdout and not stderr, but those are irrelevant to your problem at hand. You can fix them later.)

Related

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

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.

How to get cwd for relative paths?

How can I get current working directory in strace output, for system calls that are being called with relative paths? I'm trying to debug complex application that spawns multiple processes and fails to open particular file.
stat("some_file", 0x7fff6b313df0) = -1 ENOENT (No such file or directory)
Since some_file exists I believe that its located in the wrong directory. I'd tried to trace chdir calls too, but since output is interleaved its hard to deduce working directory that way. Is there a better way?
You can use the -y option and it will print the full path. Another useful flag in this situation is -P which only traces syscalls relating to a specific path, e.g.
strace -y -P "some_file"
Unfortunately -y will only print the path of file descriptors, and since your call doesn't load any it doesn't have one. A possible workaround is to interrupt the process when that syscall is run in a debugger, then you can get its working directory by inspecting /proc/<PID>/cwd. Something like this (totally untested!)
gdb --args strace -P "some_file" -e inject=open:signal=SIGSEGV
Or you may be able to use a conditional breakpoint. Something like this should work, but I had difficulty with getting GDB to follow child processes after a fork. If you only have one process it should be fine I think.
gdb your_program
break open if $_streq((char*)$rdi, "some_file")
run
print getpid()
It is quite easy, use the function char *realpath(const char *path, char *resolved_path) for the current directory.
This is my example:
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
int main(){
char *abs;
abs = realpath(".", NULL);
printf("%s\n", abs);
return 0;
}
output
root#ubuntu1504:~/patches_power_spec# pwd
/root/patches_power_spec
root#ubuntu1504:~/patches_power_spec# ./a.out
/root/patches_power_spec

printk() doesn't print in /var/log/messages

My OS Ubuntu 12.04. I wrote this Kernel Module and i use insmod and rmmod command but there isn't anything in /var/log messages. how can i fix this problem?
/*
* hello-1.c - The simplest kernel module.
*/
#include <linux/module.h> /* Needed by all modules */
#include <linux/kernel.h> /* Needed for KERN_INFO */
int init_module(void)
{
printk(KERN_INFO "Hello world 1.\n");
/*
* A non 0 return means init_module failed; module can't be loaded.
*/
return 0;
}
void cleanup_module(void)
{
printk(KERN_INFO "Goodbye world 1.\n");
}
Check whether syslog daemon process is running, since this is the process which copies printk messages from kernel ring/log message buffer to /var/log/messages if I am correct. printk messages can be seen using dmesg utility/command or messages will be in /var/log/messages. If correct loglevel is set then printk messages will be displayed on the console right away, no need to use dmesg or no need to check in /var/log/messages. printk debug messages can also be part of /var/log/syslog.
Modern Linux distributions don't use rsyslog (or any other syslog daemon) anymore. They rely on journald which is part of systemd, so the /var/log/messages file is missing and you have to use the journalctl command to read the system log.
Firstly, you should check that whether your module is properly loaded or not, by using this command
lsmod | grep "hello-1" //hello-1 is the name of your module
Since you wrote a kernel module, which prints some message. The messages from kernel and its module can be found in /var/log/syslog or you can view these kind of messages using dmesg command.
As your module prints "Hello World 1.", you should use following command to see message from your module.
dmesg | grep "Hello World 1."
Look for this in /etc/syslog.conf, the *.info... lines. These seem to control what gets logged via printk.
*.=info;*.=notice;*.=warn;\
auth,authpriv.none;\
cron,daemon.none;\
mail,news.none -/var/log/messages
I found that /proc/sys/kernel/printk only really controlled the console logging levels, not the logging to the file. And I guess check syslog is running too ;) We had exactly the same issue, KERN_INFO not going to log files and this fixed it. hth
I tried to print the kernel buffer by typing the following command :
dmesg
This will print the data written in printk

embedded linux: readdir() sometimes failing with EFAULT

I've had some readdir() issues occur in an embedded app, so I added this self-contained test at a convenient place in the app code:
FILE *f;
DIR *d;
f = fopen ("/mnt/mydir/myfile", "r");
printf ("fopen %p\r\n", f);
if (f) fclose(f);
d = opendir ("/mnt/mydir");
printf ("opendir ret %p\r\n", f);
if (d)
{
struct dirent *entry;
do
{
errno = 0;
entry = readdir (d);
printf ("readdir ret %p %s, errno %d %s\r\n", entry, entry ? entry->d_name : "", errno, strerror(errno));
} while (entry);
closedir (d);
}
/mnt/mydir is an NFS mount (although I'm not sure if that's relevant). The fopen() call to open a file in that dir always succeeds, and the opendir() on the dir also always succeeds. However, sometimes (most) the readdir() fails with errno=EFAULT.
I don't believe anywhere else in the app is doing anything with that dir. The test is exactly as written, all variables are local stack scope.
If I run it as a standalone program, it always succeeds.
Can anyone offer any suggestions as to what could cause EFAULT here? I'm pretty sure my DIR pointer variable is not being corrupted, although the DIR structure itself could be I guess. I haven't seen any evidence elsewhere of heap corruption.
From man 2 readdir page:
EFAULT Argument points outside the calling process's address space.
This means that your structure is corrupted
I think I found the problem. The uClibc implementation of opendir/readdir does a stat() on the directory, then later does a stack alloca() of size statbuf.st_blksize. My NFS directory was mounted with rsize=512KB, causing readdir() to try and allocate 512KB on the stack to hold the dents. My embedded setup does not have that much room between stacks, so at some point was hitting something below in memory and causing EFAULT.
If I change my NFS mount options to rsize=4096, it works fine.

shmget() returns ENOENT with IPC_CREAT

I'm using shmget() to allocate a shared memory segment that I then use with pthread_mutex_init() to create a mutex shared between processes. Generally, this works as expected. However, occasionally shmget() will return ENOENT. Reading the man page, this should only occur if the shmflg doesn't include IPC_CREAT, however I am including that. Here's a snip-it of my code:
shmid_ = shmget( MYLOCK_KEY_ID, sizeof(pthread_mutex_t), IPC_CREAT | IPC_EXCL | 0666 );
if ( errno == ENOENT ) {
// This should never occur since IPC_CREAT was specified
std::cerr
<< "shmget() returned ENOENT (it thinks IPC_CREAT wasn't specified).\n"
<< "This seems to be a bug in shmget()?" << std::endl;
exit(1);
}
I'm totally lost as to what could be going on. I've tried this on several systems (Linux kernels 2.6.32 and 3.3.5) but both exhibit the same behavior. Currently, when I obtain this failure mode, I just repeat the process and it usually works. But that seems kind of kludgey and I don't know if this is a bug in shmget() or if I'm just doing something wrong.
Any ideas?
Your if statement is not checking the returned value - the man pages say to check shmid_ for -1 and then check errno.
RETURN VALUE
A valid segment identifier, shmid, is returned on success, -1 on error.
What you are doing is just checking errno - it could be ENOENT after some other call to some other function that failed.

Resources