Skip to content

Commit 5997ab6

Browse files
Entropy512huangqiwu
authored andcommitted
init: Check for symlinks with lstat() not open()
Using open() with an O_NOFOLLOW flag will result in a file falsely being determined to be a symlink if the open fails for another reason. For example, a character device that isn't ready due to the underlying hardware not being initialized yet will fail to open() An example of this are any CG2900 device files prior to execution of ste-cg29xx_ctrl This uses lstat() instead of open() with O_NOFOLLOW to check whether a file is a symlink or not. Change-Id: Ie0d8d94b426c84c29b1b04d41a4cc15536cb307c
1 parent 897ae58 commit 5997ab6

File tree

1 file changed

+16
-30
lines changed

1 file changed

+16
-30
lines changed

init/builtins.c

Lines changed: 16 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -77,61 +77,47 @@ static int write_file(const char *path, const char *value)
7777
}
7878
}
7979

80-
static int _open(const char *path)
81-
{
82-
int fd;
83-
84-
fd = open(path, O_RDONLY | O_NOFOLLOW);
85-
if (fd < 0)
86-
fd = open(path, O_WRONLY | O_NOFOLLOW);
87-
88-
return fd;
89-
}
9080

9181
static int _chown(const char *path, unsigned int uid, unsigned int gid)
9282
{
93-
int fd;
9483
int ret;
9584

96-
fd = _open(path);
97-
if (fd < 0) {
85+
struct stat p_statbuf;
86+
87+
ret = lstat(path, &p_statbuf);
88+
if (ret < 0) {
9889
return -1;
9990
}
10091

101-
ret = fchown(fd, uid, gid);
102-
if (ret < 0) {
103-
int errno_copy = errno;
104-
close(fd);
105-
errno = errno_copy;
92+
if (S_ISLNK(p_statbuf.st_mode) == 1) {
93+
errno = EINVAL;
10694
return -1;
10795
}
10896

109-
close(fd);
97+
ret = chown(path, uid, gid);
11098

111-
return 0;
99+
return ret;
112100
}
113101

114102
static int _chmod(const char *path, mode_t mode)
115103
{
116-
int fd;
117104
int ret;
118105

119-
fd = _open(path);
120-
if (fd < 0) {
106+
struct stat p_statbuf;
107+
108+
ret = lstat(path, &p_statbuf);
109+
if (ret < 0) {
121110
return -1;
122111
}
123112

124-
ret = fchmod(fd, mode);
125-
if (ret < 0) {
126-
int errno_copy = errno;
127-
close(fd);
128-
errno = errno_copy;
113+
if (S_ISLNK(p_statbuf.st_mode) == 1) {
114+
errno = EINVAL;
129115
return -1;
130116
}
131117

132-
close(fd);
118+
ret = chmod(path, mode);
133119

134-
return 0;
120+
return ret;
135121
}
136122

137123
static int insmod(const char *filename, char *options)

0 commit comments

Comments
 (0)