apue code chapter 4 umask.c runs abnormal - c

I run ./umask as the following step:
[root filedir]#
[root filedir]#ls
access bar cdpwd.c changemod.c devrdev.c filetype.c ftw8 Makefile mycd.c umask.c unlink.c zap.c
access.c cdpwd changemod devrdev filetype foo ftw8.c mycd umask unlink zap
[root filedir]#./umask
[root filedir]#ll foo bar
-rw-r--r--. 1 root root 0 7月 23 11:56 bar
-rw-rw-rw-. 1 root root 0 7月 23 11:56 foo
Here is the code umask.c
#include "apue.h"
#include <fcntl.h>
#define RWRWRW (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH)
int
main(void)
{
umask(0);
if (creat("foo", RWRWRW) < 0)
err_sys("creat error for foo");
umask(S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
if (creat("bar", RWRWRW) < 0)
err_sys("creat error for bar");
exit(0);
}
as the code above,umask(S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH),why does bar has read access for group and other?
system info :
[root filedir]#umask
0022
[root filedir]#cat /etc/redhat-release
CentOS Linux release 7.6.1810 (Core)
[root filedir]#gcc
gcc 4.8.5
Linux MiWiFi-R1CL-srv 3.10.0-957.21.3.el7.x86_64 #1 SMP Tue Jun 18 16:35:19 UTC 2019 x86_64 x86_64 x86_64 GNU/Linux

It's embarrassed for me,I make a mistake.
My friend and I share the same virtual machine,he read the book faster than me.He runs 4-12 program,which the code like the following:
#include "apue.h"
int
main(void)
{
struct stat statbuf;
/* turn on set-group-ID and turn off group-execute */
if (stat("foo", &statbuf) < 0)
err_sys("stat error for foo");
if (chmod("foo", (statbuf.st_mode & ~S_IXGRP) | S_ISGID) < 0)
err_sys("chmod error for foo");
/* set absolute mode to "rw-r--r--" */
if (chmod("bar", S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH) < 0)
err_sys("chmod error for bar");
exit(0);
}
As for this problem ,I delete the foo and bar,and run ./umask,then everything run well.

Related

lsetxattr returns EPERM if attempt to set a value to symlink

I am testing simple program to add timestamp to xattr.
lsetxattr system call returns error with EPERM. Is that expected behaviour?
How can I set xattr to symlink, not follow the link?
#include <sys/types.h>
#include <attr/xattr.h>
#include <errno.h>
#include <time.h>
#include <stdio.h>
int main(int argc, char **argv){
time_t t = time(NULL);
if(lsetxattr(argv[1], "user.ts", &t, sizeof(time_t), 0) == -1){
perror(argv[1]);
}
return(0);
}
example:
> ls -l a b c
-rw-r--r-- 1 saka users 0 Feb 1 09:08 a
-rw-r--r-- 1 saka users 0 Feb 1 09:08 b
lrwxrwxrwx 1 saka users 1 Feb 1 09:08 c -> b
> ./ts a
> ./ts c
c: Operation not permitted
I tested on 3.10.0-862.14.4.el7.x86_64 with xfs or ext3.
I guess it's this:
/*
* In the user.* namespace, only regular files and directories can have
* extended attributes. For sticky directories, only the owner and
* privileged users can write attributes.
*/
And in fact, trying to set a trusted.foo attribute on a symlink with lsetxattr(2) as root works, while a user.foo fails with EPERM.

Is there a way to increase the maximum amount of messages that can be contained in a SysV message queue?

I just switched from POSIX to SysV because the limit is much higher on SysV (1024 vs 10). But I still need an higher limit. The limit should be changed at runtime, because it depends on the data the user chooses.
Using POSIX, it was possible to increase the limit but it was necessary to run the code as root every time and I cannot do that.
Is there a way to increase the limit in SysV?
As SYSV IPC are considered deprecated, it is a pity to design brand new applications with thoses old fashioned services.
POSIX message queues are based on a file system. It is usually mounted on /dev/mqueue:
$ ls -la /dev/mqueue
total 0
drwxrwxrwt 2 root root 40 dec. 25 21:02 .
drwxr-xr-x 20 root root 4600 dec. 25 20:51 ..
A message queue is created with mq_open(). The attr parameter provides the ability to set some attributes:
struct mq_attr {
long mq_flags; /* Flags (ignored for mq_open()) */
long mq_maxmsg; /* Max. # of messages on queue */
long mq_msgsize; /* Max. message size (bytes) */
long mq_curmsgs; /* # of messages currently in queue (ignored for mq_open()) */
};
According to the documentation, the /proc/sys/fs/mqueue/msg_max file defines the ceiling value for the maximum number of messages in a queue. In Linux 5.4, its default value is DFLT_MSGMAX (10) and its upper limit is HARD_MSGMAX (65536).
The defaults values are defined in the Linux source code (cf. /include/linux/ipc_namespace.h):
#define DFLT_QUEUESMAX 256
#define MIN_MSGMAX 1
#define DFLT_MSG 10U
#define DFLT_MSGMAX 10
#define HARD_MSGMAX 65536
#define MIN_MSGSIZEMAX 128
#define DFLT_MSGSIZE 8192U
#define DFLT_MSGSIZEMAX 8192
#define HARD_MSGSIZEMAX (16*1024*1024)
Here is an example program which creates a message queue. It receives as parameters the message queue name and the maximum number of messages in the queue:
#include <errno.h>
#include <pthread.h>
#include <mqueue.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(int argc, char *argv[])
{
mqd_t mqdes;
struct mq_attr attr;
if (argc != 3) {
fprintf(stderr, "Usage: %s <mq-name> <msg_max>\n", argv[0]);
exit(EXIT_FAILURE);
}
attr.mq_flags = 0;
attr.mq_maxmsg = atoi(argv[2]);
attr.mq_msgsize = 2048;
attr.mq_curmsgs = 0;
mqdes = mq_open(argv[1], O_CREAT | O_RDWR, 0777, &attr);
if (mqdes == (mqd_t) -1) {
perror("mq_open");
return 1;
}
return 0;
}
At execution time we can verify that, by default, we can't go above 10 messages for the queue:
$ gcc mq.c -o mq -lrt
$ ./mq
Usage: ./mq <mq-name> <msg_max>
$ ./mq /q0 5
$ ls -la /dev/mqueue/
total 0
drwxrwxrwt 2 root root 60 dec. 25 21:09 .
drwxr-xr-x 20 root root 4600 dec. 25 20:51 ..
-rwxrwxr-x 1 xxxx xxxx 80 dec. 25 21:09 q0
$ ./mq /q1 9
$ ./mq /q2 10
$ ./mq /q3 11
mq_open: Invalid argument
$ ls -la /dev/mqueue/
total 0
drwxrwxrwt 2 root root 100 dec. 25 21:10 .
drwxr-xr-x 20 root root 4600 dec. 25 20:51 ..
-rwxrwxr-x 1 xxxx xxxx 80 dec. 25 21:09 q0
-rwxrwxr-x 1 xxxx xxxx 80 dec. 25 21:10 q1
-rwxrwxr-x 1 xxxx xxxx 80 dec. 25 21:10 q2
Let's change the ceiling value from 10 to 256 for msg_max:
$ cat /proc/sys/fs/mqueue/msg_max
10
$ sudo sh -c "echo 256 > /proc/sys/fs/mqueue/msg_max"
$ cat /proc/sys/fs/mqueue/msg_max
256
Now it is possible to create message queues with up to 256 messages:
$ ./mq /q3 11
$ ./mq /q4 256
$ ./mq /q5 257
mq_open: Invalid argument
$ ls -la /dev/mqueue/
total 0
drwxrwxrwt 2 root root 140 dec. 25 21:16 .
drwxr-xr-x 20 root root 4600 dec. 25 20:51 ..
-rwxrwxr-x 1 xxxx xxxx 80 dec. 25 21:09 q0
-rwxrwxr-x 1 xxxx xxxx 80 dec. 25 21:10 q1
-rwxrwxr-x 1 xxxx xxxx 80 dec. 25 21:10 q2
-rwxrwxr-x 1 xxxx xxxx 80 dec. 25 21:15 q3
-rwxrwxr-x 1 xxxx xxxx 80 dec. 25 21:16 q4
But as you say, increasing the ceiling value requires super user rights. It could be possible to create a "setuid helper" which increases the ceiling value. For example, the following program sets the ceiling value passed as parameter:
#include <errno.h>
#include <fcntl.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
int main(int argc, char *argv[])
{
int fd;
int rc;
int msg_max;
if (argc != 2) {
fprintf(stderr, "Usage: %s <msg_max>\n", argv[0]);
return 1;
}
fd = open("/proc/sys/fs/mqueue/msg_max", O_RDWR);
if (fd < 0) {
perror("open()");
return 1;
}
rc = write(fd, argv[1], strlen(argv[1]));
if (rc != strlen(argv[1])) {
if (rc >= 0) {
errno = EIO;
}
perror("write()");
return 1;
}
close(fd);
return 0;
}
We can build it, change its owner/group to root and add the setuid bit:
$ gcc mq_helper.c -o mq_helper
$ sudo chown root mq_helper
$ sudo chgrp root mq_helper
$ sudo chmod 4555 mq_helper
$ ls -l mq_helper
-r-sr-xr-x 1 root root 17016 dec. 25 21:45 mq_helper
Then, it is possible to run this program from a non super user account to change the ceiling value of msg_max:
$ cat /proc/sys/fs/mqueue/msg_max
256
$ ./mq_helper 98
$ cat /proc/sys/fs/mqueue/msg_max
98

How to solve the mmap( ) failed with unexpected error EPERM ( 1 )

When I run the below program I get that the mmap() fail with the EPERM error. My expected O/P is EOPNOTSUPP error, as any flag outside the LEGACY_MAP_MASK flag would fail with EOPNOTSUPP.
#define TEST_FILE "file_to_mmap"
#define TEST_FILE_SIZE 1024
#define TEST_FILE_MODE 0600
unsigned long legacy_flags;
unsigned long map_flags;
int fd_file;
void *mapped_address;
fd_file = open(TEST_FILE, O_CREAT | O_RDWR, TEST_FILE_MODE);
legacy_flags = LEGACY_MAP_MASK;
map_flags = ~(legacy_flags) + MAP_SHARED_VALIDATE;
mapped_address = mmap(NULL, TEST_FILE_SIZE, PROT_READ | PROT_WRITE, map_flags, fd_file, 0);
if (errno == EOPNOTSUPP)
printf("Have a nice day");
Error:
mmap( ) failed with the unexpected error: EPERM (1)
uname -a: O/P:
Linux debian 4.19.0-10-amd64 #1 SMP Debian 4.19.132-1 (2020-07-24) x86_64 GNU/Linux

How do I add permissions to my ls-al c program?

I am writing code to implement the ls-al command using c program and I have gotten my code to implement it without printing permissions but I want to implement the permissions as well but cant figure out how. any suggestions? my code is below
#include <stdio.h>
#include <stdlib.h>
#include <dirent.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <time.h>
#include <pwd.h>
// Last Modified
time_t t = my_stat.st_mtime;
localtime_r(&t, &lt);
char timebuf[80];
strftime(timebuf, sizeof(timebuf), "%c", &lt);
if (pwd != 0) {
printf("%s \t %ld \t %s \t %s", pwd->pw_name, (long)my_stat.st_size, timebuf, current_directory->d_name);
printf("\n");
} else {
printf("%d \t %ld \t %s \t %s", my_stat.st_uid, (long)my_stat.st_size, timebuf, current_directory->d_name);
printf("\n");
}
}
closedir(directory);
return 0;
}
int main(int argc, char* argv[]) {
if ( argc == 1 ) {
return list_dir ( "." );
} else {
int ret = 0;
for (int i = 1; i < argc; i += 1 ) {
if ( list_dir ( argv[i] ) != 0 ) {
ret = 1;
}
}
return ret;
}
}
I have ben trying for a long time to be able to add permissions to this code but I seem to be getting stuck and am out of ideas here
the output of my code is:
kev 0 Thu Jun 20 13:39:49 2019 .
kev 0 Thu Jun 20 13:39:46 2019 ..
kev 24147 Thu Jun 20 12:24:40 2019 CMakeCache.txt
kev 0 Thu Jun 20 13:39:53 2019 CMakeFiles
kev 1426 Thu Jun 20 12:24:41 2019 cmake_install.cmake
kev 5160 Thu Jun 20 12:24:41 2019 Makefile
the expected output is:
rw-r--r-- 1 kev 0 Thu Jun 20 13:39:49 2019 .
rw-r--r-- 1 kev 0 Thu Jun 20 13:39:46 2019 ..
-rw------- 24147 Thu Jun 20 12:24:40 2019 CMakeCache.txt
rw-r--r-- kev 0 Thu Jun 20 13:39:53 2019 CMakeFiles
-rw------- kev 1426 Thu Jun 20 12:24:41 2019 cmake_install.cmake
rw-r--r-- kev 5160 Thu Jun 20 12:24:41 2019 Makefile
You will want to make use of the mode_t st_mode field of your struct stat. See stat(2):
The stat structure
All of these system calls return a stat structure, which contains the following fields:
struct stat {
dev_t st_dev; /* ID of device containing file */
ino_t st_ino; /* inode number */
mode_t st_mode; /* file type and mode */
nlink_t st_nlink; /* number of hard links */
uid_t st_uid; /* user ID of owner */
gid_t st_gid; /* group ID of owner */
dev_t st_rdev; /* device ID (if special file) */
off_t st_size; /* total size, in bytes */
blksize_t st_blksize; /* blocksize for filesystem I/O */
blkcnt_t st_blocks; /* number of 512B blocks allocated */
/* Since Linux 2.6, the kernel supports nanosecond
precision for the following timestamp fields.
For the details before Linux 2.6, see NOTES. */
struct timespec st_atim; /* time of last access */
struct timespec st_mtim; /* time of last modification */
struct timespec st_ctim; /* time of last status change */
#define st_atime st_atim.tv_sec /* Backward compatibility */
#define st_mtime st_mtim.tv_sec #define st_ctime st_ctim.tv_sec };
[...]
The file type and mode (st_mode)
POSIX refers to the st_mode bits corresponding to the mask S_IFMT (see below) as the file type, the 12 bits corresponding to the mask 07777 as the file mode bits and the least significant 9 bits (0777) as the file permission
bits.
The following mask values are defined for the file type of the st_mode field:
S_IFMT 0170000 bit mask for the file type bit field
S_IFSOCK 0140000 socket
S_IFLNK 0120000 symbolic link
S_IFREG 0100000 regular file
S_IFBLK 0060000 block device
S_IFDIR 0040000 directory
S_IFCHR 0020000 character device
S_IFIFO 0010000 FIFO
[...]
The following mask values are defined for the file mode component of the st_mode field:
S_ISUID 04000 set-user-ID bit
S_ISGID 02000 set-group-ID bit (see below)
S_ISVTX 01000 sticky bit (see below)
S_IRWXU 00700 owner has read, write, and execute permission
S_IRUSR 00400 owner has read permission
S_IWUSR 00200 owner has write permission
S_IXUSR 00100 owner has execute permission
S_IRWXG 00070 group has read, write, and execute permission
S_IRGRP 00040 group has read permission
S_IWGRP 00020 group has write permission
S_IXGRP 00010 group has execute permission
S_IRWXO 00007 others (not in group) have read, write, and execute per‐
mission
S_IROTH 00004 others have read permission
S_IWOTH 00002 others have write permission
S_IXOTH 00001 others have execute permission

strange system call semantics on nfs mount

I am writing a little test program for the open() function in C # open SuSE leap 42.2 x64.
Unfortunately the file being created gets -rwxrwxrwx permissions, although I hand over 0644 to the open() function after executing umask(0);
Could anyone please tell me, what I am doing wrong?
(I got the example code from an open book (link).
Here's my code:
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#include <string.h>
#include <unistd.h>
int main(int argc, char** argv) {
/* Zugriffsrechte 644 */
mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH;
const char *new_file;
int file_descriptor;
/* Alle Zugriffsrechte der Einschraenkungsmaske erlauben */
umask(0);
/* Argument 2 der cmd line auswerten */
if (argv[1] == NULL) {
fprintf(stderr, "usage: %s datei_zum_oeffnen\n", *argv);
return EXIT_FAILURE;
}
new_file = argv[1];
file_descriptor = open(new_file, O_WRONLY|O_EXCL|O_CREAT, 0644);
/* or var mode instead of (0644) */
if (file_descriptor == -1) {
perror("Fehler bei open ");
return EXIT_FAILURE;
}
return (EXIT_SUCCESS);
}
Either way - handing over 0644 or the variable "mode" as open()'s third argument do not work as expected and the result when executing the program (as normal user) and handing in a filename is: -rwxrwxrwx and moreover: the file belongs to root:root instead of the executing user?!
What will I have to change?
Solved.
The failure was compiling it using NetBeans 8.2.
The folders and files created by NetBeans belong to root - creating the same .c-file in my home dir and compiling it there worked perfectly.
Added:
NetBeans is not running as root.
The folder which my workspace was created in is a NTFS drive, mounted during boot with user-access - but the whole drive belongs to root in the first place. I am 99% convinced that this is what led me to wrong assumptions about NetBeans creating folders and files with wrong permissions.

Resources