You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

85 lines
1.9 KiB

Description: Fix symlink directory traversal.
Do not allow symlinks that traverse the current directoru, nor absolute
symlinks.
.
Fixes CVE-2015-0556.
Author: Guillem Jover <guillem@debian.org>
Origin: vendor
Bug-Debian: https://bugs.debian.org/774434
Forwarded: no
Last-Update: 2015-03-28
---
uxspec.c | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 54 insertions(+)
--- a/uxspec.c
+++ b/uxspec.c
@@ -120,6 +120,58 @@ int query_uxspecial(char FAR **dest, cha
}
#endif
+#if TARGET==UNIX
+static int is_link_traversal(const char *name)
+{
+ enum {
+ STATE_NONE,
+ STATE_DOTS,
+ STATE_NAME,
+ } state = STATE_NONE;
+ int ndir = 0;
+ int dots = 0;
+
+ while(*name) {
+ int c = *name++;
+
+ if (c == '/')
+ {
+ if ((state == STATE_DOTS) && (dots == 2))
+ ndir--;
+ if (ndir < 0)
+ return 1;
+ if ((state == STATE_DOTS && dots == 1) && ndir == 0)
+ return 1;
+ if (state == STATE_NONE && ndir == 0)
+ return 1;
+ if ((state == STATE_DOTS) && (dots > 2))
+ ndir++;
+ state = STATE_NONE;
+ dots = 0;
+ }
+ else if (c == '.')
+ {
+ if (state == STATE_NONE)
+ state = STATE_DOTS;
+ dots++;
+ }
+ else
+ {
+ if (state == STATE_NONE)
+ ndir++;
+ state = STATE_NAME;
+ }
+ }
+
+ if ((state == STATE_DOTS) && (dots == 2))
+ ndir--;
+ if ((state == STATE_DOTS) && (dots > 2))
+ ndir++;
+
+ return ndir < 0;
+}
+#endif
+
/* Restores the UNIX special file data */
int set_uxspecial(char FAR *storage, char *name)
@@ -156,6 +208,8 @@ int set_uxspecial(char FAR *storage, cha
l=sizeof(tmp_name)-1;
far_memmove((char FAR *)tmp_name, dptr, l);
tmp_name[l]='\0';
+ if (is_link_traversal(tmp_name))
+ return(UXSPEC_RC_ERROR);
rc=(id==UXSB_HLNK)?link(tmp_name, name):symlink(tmp_name, name);
if(!rc)
return(0);