This patch addresses a standards violation issue. The standards say a
file's access time should be updated when it gets executed. A while ago the mechanism used to exec was changed to use a more mmap based mechanism and this behavior was broken as a side-effect of that. A new vnode flag is added that gets set when the file gets executed, and the VOP_SETATTR() vnode operation gets called. The underlying filesystem is expected to handle it based on its own semantics, some filesystems don't support access time at all. Those that do should handle it in a way that does not block, does not generate I/O if possible, etc. In particular vn_start_write() has not been called. The UFS code handles it the same way as it would normally handle the access time if a file was read - the IN_ACCESS flag gets set in the inode but no other action happens at this point. The actual time update will happen later during a sync (which handles all the necessary locking). Got me into this: cperciva Discussed with: a lot with bde, a little with kan Showed patches to: phk, jeffr, standards@, arch@ Minor discussion on: arch@
This commit is contained in:
parent
2ba8e9a61b
commit
6341095e0d
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=146829
@ -284,7 +284,7 @@ do_execve(td, args, mac_p)
|
||||
register_t *stack_base;
|
||||
int error, len, i;
|
||||
struct image_params image_params, *imgp;
|
||||
struct vattr attr;
|
||||
struct vattr atimeattr, attr;
|
||||
int (*img_first)(struct image_params *);
|
||||
struct pargs *oldargs = NULL, *newargs = NULL;
|
||||
struct sigacts *oldsigacts, *newsigacts;
|
||||
@ -695,6 +695,18 @@ do_execve(td, args, mac_p)
|
||||
exec_setregs(td, imgp->entry_addr,
|
||||
(u_long)(uintptr_t)stack_base, imgp->ps_strings);
|
||||
|
||||
/*
|
||||
* Here we should update the access time of the file. This must
|
||||
* be implemented by the underlying filesystem in the same way as
|
||||
* access timestamps for a VOP_READ() because we want to avoid
|
||||
* blocking and/or I/O, and have not called vn_start_write().
|
||||
*/
|
||||
if ((imgp->vp->v_mount->mnt_flag & (MNT_NOATIME | MNT_RDONLY)) == 0) {
|
||||
VATTR_NULL(&atimeattr);
|
||||
atimeattr.va_vaflags |= VA_EXECVE_ATIME;
|
||||
(void)VOP_SETATTR(imgp->vp, &atimeattr, td->td_ucred, td);
|
||||
}
|
||||
|
||||
done1:
|
||||
/*
|
||||
* Free any resources malloc'd earlier that we didn't use.
|
||||
|
@ -284,6 +284,7 @@ struct vattr {
|
||||
*/
|
||||
#define VA_UTIMES_NULL 0x01 /* utimes argument was NULL */
|
||||
#define VA_EXCLUSIVE 0x02 /* exclusive create request */
|
||||
#define VA_EXECVE_ATIME 0x04 /* setting atime for execve */
|
||||
|
||||
/*
|
||||
* Flags for ioflag. (high 16 bits used to ask for read-ahead and
|
||||
|
@ -443,6 +443,17 @@ ufs_setattr(ap)
|
||||
((int)vap->va_bytes != VNOVAL) || (vap->va_gen != VNOVAL)) {
|
||||
return (EINVAL);
|
||||
}
|
||||
/*
|
||||
* Update the file's access time when it has been executed. We are
|
||||
* doing this here to specifically avoid some of the checks done
|
||||
* below -- this operation is done by request of the kernel and
|
||||
* should bypass some security checks. Things like read-only
|
||||
* checks get handled by other levels (e.g., ffs_update()).
|
||||
*/
|
||||
if (vap->va_vaflags & VA_EXECVE_ATIME) {
|
||||
ip->i_flag |= IN_ACCESS;
|
||||
return (0);
|
||||
}
|
||||
if (vap->va_flags != VNOVAL) {
|
||||
if (vp->v_mount->mnt_flag & MNT_RDONLY)
|
||||
return (EROFS);
|
||||
|
Loading…
Reference in New Issue
Block a user