VFS: fix last_dir not returning last directory
If the provided path was only a single component (i.e., without slashes), then last_dir would return early and skip the symlink detection (i.e., check whether the path ends in a symlink and resolve that first before returning). This bug triggered an assert in open which expects that an advance after an last_dir (with VMNT_WRITE lock) does not yield another vmnt lock.
This commit is contained in:
		
							parent
							
								
									d25ded6d3d
								
							
						
					
					
						commit
						0c1cd8720a
					
				@ -206,30 +206,13 @@ struct fproc *rfp;
 | 
			
		||||
 | 
			
		||||
	cp = strrchr(resolve->l_path, '/');
 | 
			
		||||
	if (cp == NULL) {
 | 
			
		||||
		/* Just an entry in the current working directory */
 | 
			
		||||
		struct vmnt *vmp;
 | 
			
		||||
 | 
			
		||||
		vmp = find_vmnt(start_dir->v_fs_e);
 | 
			
		||||
		if (vmp == NULL) {
 | 
			
		||||
			r = EIO;
 | 
			
		||||
			res_vp = NULL;
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
		r = lock_vmnt(vmp, resolve->l_vmnt_lock);
 | 
			
		||||
		if (r == EDEADLK) {
 | 
			
		||||
			res_vp = NULL;
 | 
			
		||||
			break;
 | 
			
		||||
		} else if (r == OK)
 | 
			
		||||
			*resolve->l_vmp = vmp;
 | 
			
		||||
 | 
			
		||||
		lock_vnode(start_dir, resolve->l_vnode_lock);
 | 
			
		||||
		*resolve->l_vnode = start_dir;
 | 
			
		||||
		dup_vnode(start_dir);
 | 
			
		||||
		if (loop_start != NULL) {
 | 
			
		||||
			unlock_vnode(loop_start);
 | 
			
		||||
			put_vnode(loop_start);
 | 
			
		||||
		}
 | 
			
		||||
		return(start_dir);
 | 
			
		||||
		/* Just an entry in the current working directory. Prepend
 | 
			
		||||
		 * "./" in front of the path and resolve it.
 | 
			
		||||
		 */
 | 
			
		||||
		strncpy(dir_entry, resolve->l_path, NAME_MAX);
 | 
			
		||||
		dir_entry[NAME_MAX] = '\0';
 | 
			
		||||
		resolve->l_path[0] = '.';
 | 
			
		||||
		resolve->l_path[1] = '\0';
 | 
			
		||||
	} else if (cp[1] == '\0') {
 | 
			
		||||
		/* Path ends in a slash. The directory entry is '.' */
 | 
			
		||||
		strcpy(dir_entry, ".");
 | 
			
		||||
@ -341,6 +324,10 @@ struct fproc *rfp;
 | 
			
		||||
 | 
			
		||||
  /* Copy the directory entry back to user_fullpath */
 | 
			
		||||
  strncpy(resolve->l_path, dir_entry, NAME_MAX + 1);
 | 
			
		||||
 | 
			
		||||
  /* Turn PATH_RET_SYMLINK flag back on if it was on */
 | 
			
		||||
  if (ret_on_symlink) resolve->l_flags |= PATH_RET_SYMLINK;
 | 
			
		||||
 | 
			
		||||
  return(res_vp);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user