symlink: limit symlink depth to avoid following cyclical links
/* msdn: There is a maximum of 31 reparse points (and * therefore symbolic links) allowed in a particular path. */ #define NFS41_MAX_SYMLINK_DEPTH 31 also added checks for the return value of nfs41_symlink_target() on open/link/rename Signed-off-by: Casey Bodley <cbodley@citi.umich.edu>
This commit is contained in:
parent
59526ba9d8
commit
870b389e8f
4 changed files with 41 additions and 0 deletions
|
|
@ -55,6 +55,10 @@
|
||||||
/* "udp" "tcp" "udp6" "tcp6" */
|
/* "udp" "tcp" "udp6" "tcp6" */
|
||||||
#define NFS41_NETWORK_ID_LEN 4
|
#define NFS41_NETWORK_ID_LEN 4
|
||||||
|
|
||||||
|
/* msdn: There is a maximum of 31 reparse points (and
|
||||||
|
* therefore symbolic links) allowed in a particular path. */
|
||||||
|
#define NFS41_MAX_SYMLINK_DEPTH 31
|
||||||
|
|
||||||
|
|
||||||
/* 424 bytes: max rpc header for reply with data */
|
/* 424 bytes: max rpc header for reply with data */
|
||||||
/* 32 bytes: max COMPOUND response */
|
/* 32 bytes: max COMPOUND response */
|
||||||
|
|
|
||||||
|
|
@ -237,11 +237,22 @@ int handle_open(nfs41_upcall *upcall)
|
||||||
&state->path, &state->parent, &state->file, &info, &state->session);
|
&state->path, &state->parent, &state->file, &info, &state->session);
|
||||||
|
|
||||||
if (status == ERROR_REPARSE) {
|
if (status == ERROR_REPARSE) {
|
||||||
|
uint32_t depth = 0;
|
||||||
/* one of the parent components was a symlink */
|
/* one of the parent components was a symlink */
|
||||||
do {
|
do {
|
||||||
|
if (++depth > NFS41_MAX_SYMLINK_DEPTH) {
|
||||||
|
status = ERROR_TOO_MANY_LINKS;
|
||||||
|
goto out_free_state;
|
||||||
|
}
|
||||||
|
|
||||||
/* replace the path with the symlink target's */
|
/* replace the path with the symlink target's */
|
||||||
status = nfs41_symlink_target(state->session,
|
status = nfs41_symlink_target(state->session,
|
||||||
&state->parent, &state->path);
|
&state->parent, &state->path);
|
||||||
|
if (status) {
|
||||||
|
/* can't do the reparse if we can't get the target */
|
||||||
|
eprintf("nfs41_symlink_target() failed with %d\n", status);
|
||||||
|
goto out_free_state;
|
||||||
|
}
|
||||||
|
|
||||||
/* redo the lookup until it doesn't return REPARSE */
|
/* redo the lookup until it doesn't return REPARSE */
|
||||||
status = nfs41_lookup(args->root, state->session,
|
status = nfs41_lookup(args->root, state->session,
|
||||||
|
|
|
||||||
|
|
@ -204,6 +204,7 @@ static int handle_nfs41_rename(setattr_upcall_args *args)
|
||||||
nfs41_abs_path dst_path;
|
nfs41_abs_path dst_path;
|
||||||
nfs41_path_fh dst_dir;
|
nfs41_path_fh dst_dir;
|
||||||
nfs41_component dst_name, *src_name;
|
nfs41_component dst_name, *src_name;
|
||||||
|
uint32_t depth = 0;
|
||||||
int status;
|
int status;
|
||||||
|
|
||||||
ZeroMemory(&dst_path, sizeof(dst_path));
|
ZeroMemory(&dst_path, sizeof(dst_path));
|
||||||
|
|
@ -252,8 +253,17 @@ static int handle_nfs41_rename(setattr_upcall_args *args)
|
||||||
&dst_path, &dst_dir, NULL, NULL, &dst_session);
|
&dst_path, &dst_dir, NULL, NULL, &dst_session);
|
||||||
|
|
||||||
while (status == ERROR_REPARSE) {
|
while (status == ERROR_REPARSE) {
|
||||||
|
if (++depth > NFS41_MAX_SYMLINK_DEPTH) {
|
||||||
|
status = ERROR_TOO_MANY_LINKS;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
/* replace the path with the symlink target's */
|
/* replace the path with the symlink target's */
|
||||||
status = nfs41_symlink_target(dst_session, &dst_dir, &dst_path);
|
status = nfs41_symlink_target(dst_session, &dst_dir, &dst_path);
|
||||||
|
if (status) {
|
||||||
|
eprintf("nfs41_symlink_target() failed with %d\n", status);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
/* redo the lookup until it doesn't return REPARSE */
|
/* redo the lookup until it doesn't return REPARSE */
|
||||||
status = nfs41_lookup(args->root, dst_session,
|
status = nfs41_lookup(args->root, dst_session,
|
||||||
|
|
@ -336,6 +346,7 @@ int handle_nfs41_link(setattr_upcall_args *args)
|
||||||
nfs41_abs_path dst_path;
|
nfs41_abs_path dst_path;
|
||||||
nfs41_path_fh dst_dir;
|
nfs41_path_fh dst_dir;
|
||||||
nfs41_component dst_name;
|
nfs41_component dst_name;
|
||||||
|
uint32_t depth = 0;
|
||||||
int status;
|
int status;
|
||||||
|
|
||||||
ZeroMemory(&dst_path, sizeof(dst_path));
|
ZeroMemory(&dst_path, sizeof(dst_path));
|
||||||
|
|
@ -356,8 +367,17 @@ int handle_nfs41_link(setattr_upcall_args *args)
|
||||||
&dst_path, &dst_dir, NULL, NULL, &dst_session);
|
&dst_path, &dst_dir, NULL, NULL, &dst_session);
|
||||||
|
|
||||||
while (status == ERROR_REPARSE) {
|
while (status == ERROR_REPARSE) {
|
||||||
|
if (++depth > NFS41_MAX_SYMLINK_DEPTH) {
|
||||||
|
status = ERROR_TOO_MANY_LINKS;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
/* replace the path with the symlink target's */
|
/* replace the path with the symlink target's */
|
||||||
status = nfs41_symlink_target(dst_session, &dst_dir, &dst_path);
|
status = nfs41_symlink_target(dst_session, &dst_dir, &dst_path);
|
||||||
|
if (status) {
|
||||||
|
eprintf("nfs41_symlink_target() failed with %d\n", status);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
/* redo the lookup until it doesn't return REPARSE */
|
/* redo the lookup until it doesn't return REPARSE */
|
||||||
status = nfs41_lookup(args->root, dst_session,
|
status = nfs41_lookup(args->root, dst_session,
|
||||||
|
|
|
||||||
|
|
@ -152,6 +152,7 @@ int nfs41_symlink_follow(
|
||||||
{
|
{
|
||||||
nfs41_abs_path path;
|
nfs41_abs_path path;
|
||||||
nfs41_path_fh file;
|
nfs41_path_fh file;
|
||||||
|
uint32_t depth = 0;
|
||||||
int status = NO_ERROR;
|
int status = NO_ERROR;
|
||||||
|
|
||||||
file.path = &path;
|
file.path = &path;
|
||||||
|
|
@ -160,6 +161,11 @@ int nfs41_symlink_follow(
|
||||||
dprintf(2, "--> nfs41_symlink_follow('%s')\n", symlink->path->path);
|
dprintf(2, "--> nfs41_symlink_follow('%s')\n", symlink->path->path);
|
||||||
|
|
||||||
do {
|
do {
|
||||||
|
if (++depth > NFS41_MAX_SYMLINK_DEPTH) {
|
||||||
|
status = ERROR_TOO_MANY_LINKS;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
/* construct the target path */
|
/* construct the target path */
|
||||||
status = nfs41_symlink_target(session, symlink, &path);
|
status = nfs41_symlink_target(session, symlink, &path);
|
||||||
if (status) goto out;
|
if (status) goto out;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue