Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 4e229d7

Browse files
Solutions to 15-4 and 15-5
1 parent 7ba5f9f commit 4e229d7

File tree

4 files changed

+160
-7
lines changed

4 files changed

+160
-7
lines changed

‎15_File_Attributes/EX_15_5.md‎

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
Exercise 15-5
2+
=============
3+
4+
The man page for [umask(2)](https://man7.org/linux/man-pages/man2/umask.2.html)
5+
says:
6+
7+
> It is impossible to use umask() to fetch a process's umask without at the same
8+
> time changing it. A second call to umask() would then be needed to restore the
9+
> umask. **The nonatomicity of these two steps provides the potential for races
10+
> in multi-threaded programs.**
11+
>
12+
> Since Linux 4.7, the umask of any process can be viewed via the Umask field of
13+
> `/proc/[pid]/status`. Inspecting this field in `/proc/self/status` allows a
14+
> process to retrieve its umask without at the same time changing it.
15+
16+
Example
17+
-------
18+
19+
```
20+
douglas@coogee:~$ umask
21+
0002
22+
douglas@coogee:~$ grep -i umask: /proc/self/status
23+
Umask: 0002
24+
```

‎15_File_Attributes/Makefile‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,5 +8,9 @@ all : t_stat my_access
88
t_stat: t_stat.c
99
gcc -o t_stat t_stat.c file_perms.c
1010

11+
my_access: my_access.c
12+
chown test_user my_access
13+
chmod u+s my_access
14+
1115
%: %.c
1216
gcc -o $@ $^

‎15_File_Attributes/README.md‎

Lines changed: 82 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,83 @@
1-
Chapter 15: File atAttributes
2-
===========================
1+
# Chapter 15: File Attributes
32

4-
Exercise 15-1
5-
-------------
3+
## Table of Contents
4+
5+
* [Exercise 15-1](#exercise-15-1)
6+
* [Exercise 15-1 (a)](#exercise-15-1-a)
7+
* [Exercise 15-1 (b)](#exercise-15-1-b)
8+
* [Exercise 15-1 (c)](#exercise-15-1-c)
9+
* [Exercise 15-2](#exercise-15-2)
10+
* [Exercise 15-3](#exercise-15-3)
11+
* [Exercise 15-4](#exercise-15-4)
12+
* [Exercise 15-5](#exercise-15-5)
13+
14+
15+
## Exercise 15-1
16+
17+
### Exercise 15-1 (a)
18+
19+
My answer is in [Ex15_1A.md](Ex15_1A.md)
20+
21+
### Exercise 15-1 (b)
22+
23+
My answer is in [Ex15_1B.md](Ex15_1B.md)
24+
25+
### Exercise 15-1 (c)
26+
27+
1. Run `make my_access`
28+
1. Run `./ex15_1c.sh >results.md`
29+
1. Results are in [Ex15_1C.md](Ex15_1C.md)
30+
31+
## Exercise 15-2
32+
33+
My answer is in [Ex15_2.md](Ex15_2.md)
34+
35+
## Exercise 15-3
36+
37+
1. Run `make t_stat`
38+
1. Run `touch test`
39+
1. Run `./t_stat test`
40+
41+
Sample output is:
42+
```
43+
File type: regular file
44+
Device containing i-node: major=253 minor=1
45+
I-node number: 51773935
46+
Mode: 100400 (r--------)
47+
Number of (hard) links: 1
48+
Ownership: UID=1000 GID=1000
49+
File size: 0 bytes
50+
Optimal I/O block size: 4096 bytes
51+
512B blocks allocated: 0
52+
Last file access: Thu Apr 1 08:26:36.752583228 2021
53+
Last file modification: Sun Mar 21 21:42:26.305140934 2021
54+
Last status change: Thu Apr 1 21:23:46.819378661 2021
55+
```
56+
57+
## Exercise 15-4
58+
59+
1. Run `make my_access`
60+
1. Run `sudo chown test_user my_access`
61+
1. Run `sudo chmod u+sx my_access`
62+
1. Run `touch test`
63+
1. Run `chmod 400 test`
64+
1. Run `./my_access -f test`
65+
1. Run `./my_access -r test`
66+
1. Run `./my_access -w test`
67+
68+
Sample output is:
69+
```
70+
$ ./my_access -f test
71+
Access for uid to 'test' using mask 0 is 0 (Success)
72+
seteuid(32767) failed: Operation not permitted
73+
$ ./my_access -r test
74+
Access for uid to 'test' using mask 4 is 0 (Success)
75+
seteuid(32766) failed: Operation not permitted
76+
$ ./my_access -w test
77+
Access for uid to 'test' using mask 2 is -1 (Permission denied)
78+
seteuid(32764) failed: Operation not permitted
79+
```
80+
81+
## Exercise 15-5
82+
83+
My answer is in [EX_15_5.md](EX_15_5.md)

‎15_File_Attributes/my_access.c‎

Lines changed: 50 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,12 @@
1515
* non-root users, the check uses an empty set of capabilities.
1616
******************************************************************************/
1717

18+
#include <errno.h>
1819
#include <stdlib.h>
1920
#include <stdio.h>
2021
#include <string.h>
22+
#include <sys/types.h>
23+
#include <sys/stat.h>
2124
#include <unistd.h>
2225

2326

@@ -26,33 +29,61 @@ void print_help(char *msg, int rc)
2629
if (msg != NULL) fprintf(stderr, "%s\n", msg);
2730
fprintf(stderr, "my_access -h\n");
2831
fprintf(stderr, "my_access -f file\n");
29-
fprintf(stderr, "my_access [-r] [-w] [-x] file\n");
32+
fprintf(stderr, "my_access [-r] [-w] [-x] [-u uid] file\n");
3033
fprintf(stderr, "\t-h\tPrint this help message\n");
3134
fprintf(stderr, "\t-f\tTest for existence of file\n");
3235
fprintf(stderr, "\t-r\tTest whether effective user can read file\n");
3336
fprintf(stderr, "\t-w\tTest whether effective user can write file\n");
3437
fprintf(stderr, "\t-x\tTest whether effective user can execute file\n");
38+
fprintf(stderr, "\n\t-u\tEffective User ID to use\n");
39+
3540
exit(rc);
3641
}
3742

38-
int my_access(const char *pathname, int mode)
43+
int euid_access(const char *pathname, int mode, uid_tuid)
3944
{
45+
int save_errno = 0;
46+
int res = 0;
47+
48+
struct stat statbuf;
49+
50+
res = access(pathname, mode);
51+
52+
if (res == 0) return 0;
53+
54+
save_errno = errno;
55+
56+
if (stat(pathname, &statbuf) == -1) return -1;
57+
58+
if (mode == F_OK) return 0; /* File exists */
59+
60+
if ((uid == statbuf.st_uid) &&
61+
((statbuf.st_mode & S_IRWXU) == mode << 8))
62+
{
63+
return 0; /* owner has required permissions */
64+
}
65+
66+
errno = EACCES;
67+
return -1;
4068
}
4169

4270
int
4371
main(int argc, char *argv[])
4472
{
4573
int fname; /* Location of filename argument in argv[] */
74+
uid_t euid; /* effective user-id */
4675
int opt;
4776
int f_mode = 0; /* F_OK maps to zero (0) */
4877
int rwx_mode = 0;
4978
char *invalid_opt_msg_fmt = "'%c' is an invalid option";
5079
char *invalid_opt_msg;
5180
char *file_missing_msg = "file name is missing";
5281
char *conflict_args_msg = "specify either -f or a combination of -r -w -x";
82+
char *uid_msg = "Access for uid to '%s' using mask %d is %d (%m)\n";
83+
char *euid_msg = "Access for euid to '%s' using mask %d is %d (%m)\n";
5384

5485
invalid_opt_msg = malloc(strlen(invalid_opt_msg_fmt));
55-
while ((opt = getopt(argc, argv, ":hfrwx")) != -1)
86+
while ((opt = getopt(argc, argv, ":hfru:wx")) != -1)
5687
{
5788
switch (opt)
5889
{
@@ -61,6 +92,7 @@ main(int argc, char *argv[])
6192
case 'r': rwx_mode |= R_OK; break;
6293
case 'w': rwx_mode |= W_OK; break;
6394
case 'x': rwx_mode |= X_OK; break;
95+
case 'u': euid = atoi(optarg); break;
6496
case '?':
6597
sprintf(invalid_opt_msg, invalid_opt_msg_fmt, (char)optopt);
6698
print_help(invalid_opt_msg, EXIT_FAILURE);
@@ -80,5 +112,20 @@ main(int argc, char *argv[])
80112
if (rwx_mode != 0) print_help(conflict_args_msg, EXIT_FAILURE);
81113
}
82114

115+
int mode = (f_mode) ? F_OK : rwx_mode;
116+
int res = 0;
117+
118+
res = access(argv[fname], mode);
119+
printf(uid_msg, argv[fname], mode, res);
120+
121+
if (seteuid(euid) != 0)
122+
{
123+
fprintf(stderr, "seteuid(%d) failed: %m\n", euid);
124+
exit(EXIT_FAILURE);
125+
}
126+
127+
res = euid_access(argv[fname], mode, euid);
128+
printf(euid_msg, argv[fname], mode, res);
129+
83130
exit(EXIT_SUCCESS);
84131
}

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /