|
Lines 176-182
Link Here
|
| 176 |
* to remove it if we created it and its length is 0. |
176 |
* to remove it if we created it and its length is 0. |
| 177 |
*/ |
177 |
*/ |
| 178 |
|
178 |
|
| 179 |
if (pflag && setfile(fs, to_fd)) |
179 |
/* do not copy flags at this time, or the next (f)chmod() fails */ |
|
|
180 |
if (pflag && setfile(fs, to_fd, 0)) |
| 180 |
rval = 1; |
181 |
rval = 1; |
| 181 |
/* |
182 |
/* |
| 182 |
* If the source was setuid or setgid, lose the bits unless the |
183 |
* If the source was setuid or setgid, lose the bits unless the |
|
Lines 194-199
Link Here
|
| 194 |
rval = 1; |
195 |
rval = 1; |
| 195 |
} |
196 |
} |
| 196 |
} |
197 |
} |
|
|
198 |
|
| 199 |
/* setfile() again, just for the file flags */ |
| 200 |
if (pflag && setfile(fs, to_fd, 2)) |
| 201 |
rval = 1; |
| 202 |
|
| 197 |
(void)close(from_fd); |
203 |
(void)close(from_fd); |
| 198 |
if (close(to_fd)) { |
204 |
if (close(to_fd)) { |
| 199 |
warn("%s", to.p_path); |
205 |
warn("%s", to.p_path); |
|
Lines 239-245
Link Here
|
| 239 |
warn("mkfifo: %s", to.p_path); |
245 |
warn("mkfifo: %s", to.p_path); |
| 240 |
return (1); |
246 |
return (1); |
| 241 |
} |
247 |
} |
| 242 |
return (pflag ? setfile(from_stat, 0) : 0); |
248 |
return (pflag ? setfile(from_stat, 0, 1) : 0); |
| 243 |
} |
249 |
} |
| 244 |
|
250 |
|
| 245 |
int |
251 |
int |
|
Lines 255-268
Link Here
|
| 255 |
warn("mknod: %s", to.p_path); |
261 |
warn("mknod: %s", to.p_path); |
| 256 |
return (1); |
262 |
return (1); |
| 257 |
} |
263 |
} |
| 258 |
return (pflag ? setfile(from_stat, 0) : 0); |
264 |
return (pflag ? setfile(from_stat, 0, 1) : 0); |
| 259 |
} |
265 |
} |
| 260 |
|
266 |
|
| 261 |
|
267 |
|
| 262 |
int |
268 |
int |
| 263 |
setfile(fs, fd) |
269 |
setfile(fs, fd, setflags) |
| 264 |
register struct stat *fs; |
270 |
register struct stat *fs; |
| 265 |
int fd; |
271 |
int fd, setflags; |
|
|
272 |
/* values for setflags: |
| 273 |
0 - do not touch fd's flags; |
| 274 |
1 - set fd's flags to match fs's flags; |
| 275 |
2 - ONLY set fd's flags to fs's flags, do nothing more |
| 276 |
|
| 277 |
the only reason for setflags to be 2 is in copy_file() |
| 278 |
after the set[ug]id fixup; this would be better if |
| 279 |
the fixup itself were moved here. |
| 280 |
*/ |
| 266 |
{ |
281 |
{ |
| 267 |
static struct timeval tv[2]; |
282 |
static struct timeval tv[2]; |
| 268 |
struct stat ts; |
283 |
struct stat ts; |
|
Lines 292-319
Link Here
|
| 292 |
* the mode; current BSD behavior is to remove all setuid bits on |
307 |
* the mode; current BSD behavior is to remove all setuid bits on |
| 293 |
* chown. If chown fails, lose setuid/setgid bits. |
308 |
* chown. If chown fails, lose setuid/setgid bits. |
| 294 |
*/ |
309 |
*/ |
| 295 |
if (!gotstat || fs->st_uid != ts.st_uid || fs->st_gid != ts.st_gid) |
310 |
|
| 296 |
if (fd ? fchown(fd, fs->st_uid, fs->st_gid) : |
311 |
/* Oops. Are we called *after* the copy_file() set[ug]id fixup? */ |
| 297 |
chown(to.p_path, fs->st_uid, fs->st_gid)) { |
312 |
if (setflags != 2) { |
| 298 |
if (errno != EPERM) { |
313 |
if (!gotstat || fs->st_uid != ts.st_uid || fs->st_gid != ts.st_gid) |
|
|
314 |
if (fd ? fchown(fd, fs->st_uid, fs->st_gid) : |
| 315 |
chown(to.p_path, fs->st_uid, fs->st_gid)) { |
| 316 |
if (errno != EPERM) { |
| 317 |
warn("chown: %s", to.p_path); |
| 318 |
rval = 1; |
| 319 |
} |
| 320 |
fs->st_mode &= ~(S_ISUID | S_ISGID); |
| 321 |
} |
| 322 |
|
| 323 |
if (!gotstat || fs->st_mode != ts.st_mode) |
| 324 |
if (fd ? fchmod(fd, fs->st_mode) : chmod(to.p_path, fs->st_mode)) { |
| 299 |
warn("chown: %s", to.p_path); |
325 |
warn("chown: %s", to.p_path); |
| 300 |
rval = 1; |
326 |
rval = 1; |
| 301 |
} |
327 |
} |
| 302 |
fs->st_mode &= ~(S_ISUID | S_ISGID); |
328 |
} |
| 303 |
} |
|
|
| 304 |
|
| 305 |
if (!gotstat || fs->st_mode != ts.st_mode) |
| 306 |
if (fd ? fchmod(fd, fs->st_mode) : chmod(to.p_path, fs->st_mode)) { |
| 307 |
warn("chown: %s", to.p_path); |
| 308 |
rval = 1; |
| 309 |
} |
| 310 |
|
329 |
|
| 311 |
if (!gotstat || fs->st_flags != ts.st_flags) |
330 |
if (setflags) { |
| 312 |
if (fd ? |
331 |
if (!gotstat || fs->st_flags != ts.st_flags) |
| 313 |
fchflags(fd, fs->st_flags) : chflags(to.p_path, fs->st_flags)) { |
332 |
if (fd ? |
| 314 |
warn("chflags: %s", to.p_path); |
333 |
fchflags(fd, fs->st_flags) : chflags(to.p_path, fs->st_flags)) { |
| 315 |
rval = 1; |
334 |
warn("chflags: %s", to.p_path); |
| 316 |
} |
335 |
rval = 1; |
|
|
336 |
} |
| 337 |
} |
| 317 |
|
338 |
|
| 318 |
return (rval); |
339 |
return (rval); |
| 319 |
} |
340 |
} |