-
Notifications
You must be signed in to change notification settings - Fork 1.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
FreeBSD: Fix file descriptor leak on pool import. #15630
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -50,26 +50,65 @@ int | |
zfs_file_open(const char *path, int flags, int mode, zfs_file_t **fpp) | ||
{ | ||
struct thread *td; | ||
int rc, fd; | ||
struct vnode *vp; | ||
struct file *fp; | ||
struct nameidata nd; | ||
int error; | ||
|
||
td = curthread; | ||
pwd_ensure_dirs(); | ||
/* 12.x doesn't take a const char * */ | ||
rc = kern_openat(td, AT_FDCWD, __DECONST(char *, path), | ||
UIO_SYSSPACE, flags, mode); | ||
if (rc) | ||
return (SET_ERROR(rc)); | ||
fd = td->td_retval[0]; | ||
td->td_retval[0] = 0; | ||
if (fget(curthread, fd, &cap_no_rights, fpp)) | ||
kern_close(td, fd); | ||
|
||
KASSERT((flags & (O_EXEC | O_PATH)) == 0, | ||
("invalid flags: 0x%x", flags)); | ||
KASSERT((flags & O_ACCMODE) != O_ACCMODE, | ||
("invalid flags: 0x%x", flags)); | ||
flags = FFLAGS(flags); | ||
|
||
error = falloc_noinstall(td, &fp); | ||
if (error != 0) { | ||
return (error); | ||
} | ||
fp->f_flag = flags & FMASK; | ||
|
||
#if __FreeBSD_version >= 1400043 | ||
NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, path); | ||
#else | ||
NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, path, td); | ||
#endif | ||
error = vn_open(&nd, &flags, mode, fp); | ||
if (error != 0) { | ||
falloc_abort(td, fp); | ||
return (SET_ERROR(error)); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This seems to leak buffer in nd There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Do you mean NDFREE_PNBUF() should be moved up? It is allocated by successful vn_open(), not by NDINIT(), so I think we should be fine. |
||
} | ||
NDFREE_PNBUF(&nd); | ||
vp = nd.ni_vp; | ||
fp->f_vnode = vp; | ||
if (fp->f_ops == &badfileops) { | ||
finit_vnode(fp, flags, NULL, &vnops); | ||
} | ||
VOP_UNLOCK(vp); | ||
if (vp->v_type != VREG) { | ||
zfs_file_close(fp); | ||
return (SET_ERROR(EACCES)); | ||
} | ||
|
||
if (flags & O_TRUNC) { | ||
error = fo_truncate(fp, 0, td->td_ucred, td); | ||
if (error != 0) { | ||
zfs_file_close(fp); | ||
return (SET_ERROR(error)); | ||
} | ||
} | ||
|
||
*fpp = fp; | ||
|
||
return (0); | ||
} | ||
|
||
void | ||
zfs_file_close(zfs_file_t *fp) | ||
{ | ||
fo_close(fp, curthread); | ||
fdrop(fp, curthread); | ||
} | ||
|
||
static int | ||
|
@@ -260,7 +299,7 @@ zfs_file_get(int fd) | |
void | ||
zfs_file_put(zfs_file_t *fp) | ||
{ | ||
fdrop(fp, curthread); | ||
zfs_file_close(fp); | ||
} | ||
|
||
loff_t | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is the source of the flags? If the whole O_* namespace is valid for flags then some validation is required, because a lot of flags combinations are invalid and probably result in contradictory state of the file/vnode.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks. I added some asserts and moved FFLAGS() to before this line.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I still think that if going forward with struct file * as handle, and with using vn_open()-like open, it is much better to split kern_openat() and use that. You cleared some flags, but the other important part of openat() handles special errors and fileops.