ref: 3d71a606cc2643a720a79752c7dbcebd816dcebc
parent: 22b296500a2ba685943388ff28c7d8b8f42cbeb5
author: Sigrid Solveig Haflínudóttir <ftrvxmtrx@gmail.com>
date: Sat Nov 14 19:24:05 EST 2020
fix truncation permission check; fix writing beyond file end
--- a/ext4srv.c
+++ b/ext4srv.c
@@ -6,6 +6,8 @@
#include "group.h"
#include "common.h"
+#define MIN(a,b) ((a)<(b)?(a):(b))
+
int mainstacksize = 65536;
typedef struct Aux Aux;
@@ -29,7 +31,7 @@
};
static Opts opts;
-
+static u8int zero[65536];
static char Eperm[] = "permission denied";
static char *
@@ -103,6 +105,8 @@
default:
return 0;
}
+ if(p & OTRUNC)
+ p |= AWRITE;
if((s = fullpath(a)) == nil)
return -1;
@@ -343,6 +347,7 @@
goto ext4errorrm;
ext4_owner_set(s, a->uid, ext4_inode_get_gid(&inode));
+ free(a->path);
a->path = strdup(strchr(s+1, '/')+1);
free(s);
r->ofcall.iounit = 0;
@@ -445,25 +450,24 @@
rread(Req *r)
{
ulong n;
+ int res;
Aux *a;
a = r->fid->aux;
if(a->type == Adir && a->dir != nil){
dirread9p(r, dirgen, a);
- respond(r, nil);
- return;
}else if(a->type == Afile && a->file != nil){
- ext4_fseek(a->file, r->ifcall.offset, 0);
- if(ext4_fread(a->file, r->ofcall.data, r->ifcall.count, &n) != 0){
- respond(r, "i/o error");
- }else{
- r->ofcall.count = n;
- respond(r, nil);
+ if(ext4_fseek(a->file, r->ifcall.offset, SEEK_SET) != 0)
+ n = 0;
+ else if((res = ext4_fread(a->file, r->ofcall.data, r->ifcall.count, &n)) != 0){
+ respond(r, errno2s(res));
+ return;
}
- return;
+
+ r->ofcall.count = n;
}
- respond(r, "eh?");
+ respond(r, nil);
}
static void
@@ -476,19 +480,25 @@
a = r->fid->aux;
if(a->type == Adir){
respond(r, "can't write to dir");
- return;
}else if(a->type == Afile){
- ext4_fseek(a->file, r->ifcall.offset, SEEK_SET);
- if((res = ext4_fwrite(a->file, r->ifcall.data, r->ifcall.count, &n)) != 0)
- respond(r, errno2s(res));
- else{
- r->ofcall.count = n;
- respond(r, nil);
+ while(ext4_fsize(a->file) < r->ifcall.offset){
+ ext4_fseek(a->file, 0, SEEK_END);
+ if((res = ext4_fwrite(a->file, zero, MIN(r->ifcall.offset-ext4_fsize(a->file), sizeof(zero)), &n)) != 0)
+ goto ext4error;
}
- return;
+ if((res = ext4_fseek(a->file, r->ifcall.offset, SEEK_SET)) != 0)
+ goto ext4error;
+ if((res = ext4_fwrite(a->file, r->ifcall.data, r->ifcall.count, &n)) != 0)
+ goto ext4error;
+
+ r->ofcall.count = n;
+ respond(r, nil);
}
- respond(r, "eh?");
+ return;
+
+ext4error:
+ respond(r, errno2s(res));
}
static void
@@ -758,20 +768,14 @@
Aux *a, *c;
a = oldfid->aux;
- switch(a->type){
- case Afile:
- case Adir:
- if((c = calloc(1, sizeof(*c))) == nil)
- return "memory";
- memmove(c, a, sizeof(*c));
- c->path = strdup(a->path);
- c->file = nil;
- c->dir = nil;
- break;
- default:
- return "unknown aux type";
- }
+ if((c = calloc(1, sizeof(*c))) == nil)
+ return "memory";
+ memmove(c, a, sizeof(*c));
+ c->path = strdup(a->path);
+ c->file = nil;
+ c->dir = nil;
+
incref(c->p);
newfid->aux = c;
@@ -798,12 +802,9 @@
ext4_fclose(a->file);
free(a->file);
}
- }else{
- /* that would be a BUG */
- return;
}
- if(decref(a->p) == 0)
+ if(decref(a->p) < 1)
closepart(a->p);
free(a->path);
free(a);