diff options
| author | Denys Vlasenko <vda.linux@googlemail.com> | 2021-06-24 01:07:56 +0200 |
|---|---|---|
| committer | Denys Vlasenko <vda.linux@googlemail.com> | 2021-06-24 01:07:56 +0200 |
| commit | 9468ea06d2445f774dd923fdfdea04209984fbf4 (patch) | |
| tree | 160eb64f9af8ba0a4f1a6596bee17b2bd2da3890 | |
| parent | 0e55af6c61a5420ffbeae990928b0fc546a7ef06 (diff) | |
| download | busybox-w32-9468ea06d2445f774dd923fdfdea04209984fbf4.tar.gz busybox-w32-9468ea06d2445f774dd923fdfdea04209984fbf4.tar.bz2 busybox-w32-9468ea06d2445f774dd923fdfdea04209984fbf4.zip | |
lsattr,chattr: do not open e.g. device files unless asked directly; do not follow links
Add O_NOFOLLOW (and O_NOCTTY for good measure) to open calls like e2fsprogs does.
In lsattr, when recursing, operate only on regular files, symlinks, and directories.
(Otherwise, "lsattr /dev" can e.g. open a watchdog device... not good).
At this time, looks like chattr/lsattr can't operate on symlink inodes -
ioctls do not work on open(O_PATH | O_NOFOLLOW) fds.
function old new delta
lsattr_dir_proc 168 203 +35
change_attributes 410 408 -2
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 1/1 up/down: 35/-2) Total: 33 bytes
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
| -rw-r--r-- | e2fsprogs/chattr.c | 9 | ||||
| -rw-r--r-- | e2fsprogs/lsattr.c | 15 |
2 files changed, 18 insertions, 6 deletions
diff --git a/e2fsprogs/chattr.c b/e2fsprogs/chattr.c index e599abae7..f436cd91e 100644 --- a/e2fsprogs/chattr.c +++ b/e2fsprogs/chattr.c | |||
| @@ -162,8 +162,6 @@ static void change_attributes(const char *name, struct globals *gp) | |||
| 162 | bb_perror_msg("can't stat '%s'", name); | 162 | bb_perror_msg("can't stat '%s'", name); |
| 163 | return; | 163 | return; |
| 164 | } | 164 | } |
| 165 | if (S_ISLNK(st.st_mode) && gp->recursive) | ||
| 166 | return; | ||
| 167 | 165 | ||
| 168 | /* Don't try to open device files, fifos etc. We probably | 166 | /* Don't try to open device files, fifos etc. We probably |
| 169 | * ought to display an error if the file was explicitly given | 167 | * ought to display an error if the file was explicitly given |
| @@ -172,7 +170,12 @@ static void change_attributes(const char *name, struct globals *gp) | |||
| 172 | if (!S_ISREG(st.st_mode) && !S_ISLNK(st.st_mode) && !S_ISDIR(st.st_mode)) | 170 | if (!S_ISREG(st.st_mode) && !S_ISLNK(st.st_mode) && !S_ISDIR(st.st_mode)) |
| 173 | return; | 171 | return; |
| 174 | 172 | ||
| 175 | fd = open_or_warn(name, O_RDONLY | O_NONBLOCK); /* neither read nor write asked for */ | 173 | /* There is no way to run needed ioctls on a symlink. |
| 174 | * open(O_PATH | O_NOFOLLOW) _can_ be used to get a fd referring to the symlink, | ||
| 175 | * but ioctls fail on such a fd (tried on 4.12.0 kernel). | ||
| 176 | * e2fsprogs-1.46.2 uses open(O_NOFOLLOW), it fails on symlinks. | ||
| 177 | */ | ||
| 178 | fd = open_or_warn(name, O_RDONLY | O_NONBLOCK | O_NOCTTY | O_NOFOLLOW); | ||
| 176 | if (fd >= 0) { | 179 | if (fd >= 0) { |
| 177 | int r; | 180 | int r; |
| 178 | 181 | ||
diff --git a/e2fsprogs/lsattr.c b/e2fsprogs/lsattr.c index b4ed12d50..545afa7f5 100644 --- a/e2fsprogs/lsattr.c +++ b/e2fsprogs/lsattr.c | |||
| @@ -49,8 +49,13 @@ static void list_attributes(const char *name) | |||
| 49 | unsigned fsflags; | 49 | unsigned fsflags; |
| 50 | int fd, r; | 50 | int fd, r; |
| 51 | 51 | ||
| 52 | fd = open_or_warn(name, O_RDONLY | O_NONBLOCK); /* neither read nor write asked for */ | 52 | /* There is no way to run needed ioctls on a symlink. |
| 53 | if (fd < 0) /* for example, dangling links */ | 53 | * open(O_PATH | O_NOFOLLOW) _can_ be used to get a fd referring to the symlink, |
| 54 | * but ioctls fail on such a fd (tried on 4.12.0 kernel). | ||
| 55 | * e2fsprogs-1.46.2 uses open(O_NOFOLLOW), it fails on symlinks. | ||
| 56 | */ | ||
| 57 | fd = open_or_warn(name, O_RDONLY | O_NONBLOCK | O_NOCTTY | O_NOFOLLOW); | ||
| 58 | if (fd < 0) | ||
| 54 | return; | 59 | return; |
| 55 | 60 | ||
| 56 | if (option_mask32 & OPT_PROJID) { | 61 | if (option_mask32 & OPT_PROJID) { |
| @@ -102,8 +107,12 @@ static int FAST_FUNC lsattr_dir_proc(const char *dir_name, | |||
| 102 | 107 | ||
| 103 | if (lstat(path, &st) != 0) | 108 | if (lstat(path, &st) != 0) |
| 104 | bb_perror_msg("can't stat '%s'", path); | 109 | bb_perror_msg("can't stat '%s'", path); |
| 110 | |||
| 105 | else if (de->d_name[0] != '.' || (option_mask32 & OPT_ALL)) { | 111 | else if (de->d_name[0] != '.' || (option_mask32 & OPT_ALL)) { |
| 106 | list_attributes(path); | 112 | /* Don't try to open device files, fifos etc */ |
| 113 | if (S_ISREG(st.st_mode) || S_ISLNK(st.st_mode) || S_ISDIR(st.st_mode)) | ||
| 114 | list_attributes(path); | ||
| 115 | |||
| 107 | if (S_ISDIR(st.st_mode) && (option_mask32 & OPT_RECUR) | 116 | if (S_ISDIR(st.st_mode) && (option_mask32 & OPT_RECUR) |
| 108 | && !DOT_OR_DOTDOT(de->d_name) | 117 | && !DOT_OR_DOTDOT(de->d_name) |
| 109 | ) { | 118 | ) { |
