Improve the robustness of MSDOSFSMNT_KICONV handling:

- Use copyinstr() to read cs_win, cs_dos, cs_local strings from the
  mount argument structure instead of reading through user-space pointers(!).
- When mounting a filesystem, or updating an existing mount, only try to
  update the iconv handles from the information in the mount argument
  structure if the structure itself has the MSDOSFSMNT_KICONV flag set.
- Attempt to handle failure of update_mp() in the MNT_UPDATE case.
This commit is contained in:
Tim J. Robbins 2004-08-26 13:16:44 +00:00
parent 29c78ab315
commit 1a9415af17

View File

@ -103,6 +103,9 @@ static vfs_sync_t msdosfs_sync;
static vfs_unmount_t msdosfs_unmount;
static vfs_vptofh_t msdosfs_vptofh;
/* Maximum length of a character set name (arbitrary). */
#define MAXCSLEN 64
static int
update_mp(mp, argp, td)
struct mount *mp;
@ -110,24 +113,45 @@ update_mp(mp, argp, td)
struct thread *td;
{
struct msdosfsmount *pmp = VFSTOMSDOSFS(mp);
char *dos, *win, *local;
int error;
if (argp->flags & MSDOSFSMNT_KICONV) {
if (msdosfs_iconv) {
win = malloc(MAXCSLEN, M_TEMP, M_WAITOK);
local = malloc(MAXCSLEN, M_TEMP, M_WAITOK);
dos = malloc(MAXCSLEN, M_TEMP, M_WAITOK);
if ((error = copyinstr(argp->cs_win, win, MAXCSLEN,
NULL)) != 0)
goto iconvdone;
if ((error = copyinstr(argp->cs_local, local, MAXCSLEN,
NULL)) != 0)
goto iconvdone;
if ((error = copyinstr(argp->cs_dos, dos, MAXCSLEN,
NULL)) != 0)
goto iconvdone;
msdosfs_iconv->open(win, local, &pmp->pm_u2w);
msdosfs_iconv->open(local, win, &pmp->pm_w2u);
msdosfs_iconv->open(dos, local, &pmp->pm_u2d);
msdosfs_iconv->open(local, dos, &pmp->pm_d2u);
iconvdone: free(win, M_TEMP);
free(local, M_TEMP);
free(dos, M_TEMP);
if (error != 0)
return (error);
} else {
pmp->pm_w2u = NULL;
pmp->pm_u2w = NULL;
pmp->pm_d2u = NULL;
pmp->pm_u2d = NULL;
}
}
pmp->pm_gid = argp->gid;
pmp->pm_uid = argp->uid;
pmp->pm_mask = argp->mask & ALLPERMS;
pmp->pm_dirmask = argp->dirmask & ALLPERMS;
pmp->pm_flags |= argp->flags & MSDOSFSMNT_MNTOPT;
if (pmp->pm_flags & MSDOSFSMNT_KICONV && msdosfs_iconv) {
msdosfs_iconv->open(argp->cs_win, argp->cs_local , &pmp->pm_u2w);
msdosfs_iconv->open(argp->cs_local, argp->cs_win , &pmp->pm_w2u);
msdosfs_iconv->open(argp->cs_dos, argp->cs_local , &pmp->pm_u2d);
msdosfs_iconv->open(argp->cs_local, argp->cs_dos , &pmp->pm_d2u);
} else {
pmp->pm_w2u = NULL;
pmp->pm_u2w = NULL;
pmp->pm_d2u = NULL;
pmp->pm_u2d = NULL;
}
if (pmp->pm_flags & MSDOSFSMNT_NOWIN95)
pmp->pm_flags |= MSDOSFSMNT_SHORTNAME;
@ -289,7 +313,10 @@ msdosfs_omount(mp, path, data, td)
error = update_mp(mp, &args, td);
if (error) {
msdosfs_unmount(mp, MNT_FORCE, td);
if ((mp->mnt_flag & MNT_UPDATE) == 0)
msdosfs_unmount(mp, MNT_FORCE, td);
else
vrele(devvp);
return error;
}
(void) copyinstr(args.fspec, mp->mnt_stat.f_mntfromname, MNAMELEN - 1,