1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Ivan Trubach <mr.trubach@icloud.com>
Date: Sat, 27 Jul 2024 20:46:31 +0300
Subject: [PATCH 14/19] Fix segfault when copying xattr buffers
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
xar_linuxattr_read allocates an internal buffer and incrementally copies
the data to xar_attrcopy_to_heap’s inbuf. This change fixes the offset
handling by rewriting xar_linuxattr_read function from scratch (with an
arguably cleaner implementation).
---
xar/lib/linuxattr.c | 68 +++++++++++++++++++++++++++------------------
1 file changed, 41 insertions(+), 27 deletions(-)
diff --git a/xar/lib/linuxattr.c b/xar/lib/linuxattr.c
index 496dd82..30c85c2 100644
--- a/xar/lib/linuxattr.c
+++ b/xar/lib/linuxattr.c
@@ -97,39 +97,50 @@ struct _linuxattr_context{
#define LINUXATTR_CONTEXT(x) ((struct _linuxattr_context *)(x))
-int32_t xar_linuxattr_read(xar_t x, xar_file_t f, void * buf, size_t len, void *context) {
-
- if( !LINUXATTR_CONTEXT(context)->buf ) {
- int r;
- LINUXATTR_CONTEXT(context)->bufsz = 1024;
+int32_t xar_linuxattr_read(xar_t x, xar_file_t f, void *inbuf, size_t len, void *context) {
+ void *buf;
+ int bufsz, off, ret;
+ int r;
+
+ buf = LINUXATTR_CONTEXT(context)->buf;
+ bufsz = LINUXATTR_CONTEXT(context)->bufsz;
+ off = LINUXATTR_CONTEXT(context)->off;
+
+ if (buf == NULL) {
+ bufsz = 1024;
AGAIN2:
- LINUXATTR_CONTEXT(context)->buf = malloc(LINUXATTR_CONTEXT(context)->bufsz);
- if(!LINUXATTR_CONTEXT(context)->buf)
- goto AGAIN2;
- memset(LINUXATTR_CONTEXT(context)->buf, 0, LINUXATTR_CONTEXT(context)->bufsz);
- r = lgetxattr(LINUXATTR_CONTEXT(context)->file, LINUXATTR_CONTEXT(context)->attrname, LINUXATTR_CONTEXT(context)->buf, LINUXATTR_CONTEXT(context)->bufsz);
- if( r < 0 ) {
- switch(errno) {
- case ERANGE: LINUXATTR_CONTEXT(context)->bufsz *= 2; free(LINUXATTR_CONTEXT(context)->buf); goto AGAIN2;
- case ENOTSUP: free(LINUXATTR_CONTEXT(context)->buf); return 0;
- default: break;
+ buf = malloc(bufsz);
+ if (!buf) {
+ return -1;
+ }
+ memset(buf, 0, bufsz);
+ r = lgetxattr(LINUXATTR_CONTEXT(context)->file, LINUXATTR_CONTEXT(context)->attrname, buf, bufsz);
+ if (r < 0) {
+ free(buf);
+ switch (errno) {
+ case ERANGE:
+ bufsz *= 2;
+ goto AGAIN2;
+ case ENOTSUP:
+ return 0;
};
return -1;
}
+ LINUXATTR_CONTEXT(context)->buf = buf;
LINUXATTR_CONTEXT(context)->bufsz = r;
+ bufsz = r;
}
- if( (LINUXATTR_CONTEXT(context)->bufsz-LINUXATTR_CONTEXT(context)->off) <= len ) {
- int32_t ret;
- ret = LINUXATTR_CONTEXT(context)->bufsz - LINUXATTR_CONTEXT(context)->off;
- memcpy(buf, ((char *)LINUXATTR_CONTEXT(context)->buf)+LINUXATTR_CONTEXT(context)->off, ret);
- LINUXATTR_CONTEXT(context)->off += ret;
- return(ret);
- } else {
- memcpy(buf, ((char *)LINUXATTR_CONTEXT(context)->buf)+LINUXATTR_CONTEXT(context)->off, len);
- LINUXATTR_CONTEXT(context)->buf = ((char *)LINUXATTR_CONTEXT(context)->buf) + len;
- return len;
+ ret = bufsz - off;
+ if (ret <= len) {
+ memcpy(inbuf, ((char *)buf) + off, ret);
+ LINUXATTR_CONTEXT(context)->off = bufsz;
+ return ret;
}
+
+ memcpy(inbuf, ((char *)buf) + off, len);
+ LINUXATTR_CONTEXT(context)->off += len;
+ return len;
}
int32_t xar_linuxattr_write(xar_t x, xar_file_t f, void *buf, size_t len, void *context) {
@@ -185,6 +196,7 @@ TRYAGAIN:
for( i=buf; (i-buf) < ret; i += strlen(i)+1 ) {
xar_ea_t e;
+ int rc;
context.bufsz = 0;
context.off = 0;
@@ -194,11 +206,13 @@ TRYAGAIN:
xar_ea_pset(f, e, "fstype", fsname);
context.attrname = i;
context.ea = e;
- if (XAR(x)->attrcopy_to_heap(x, f, xar_ea_root(e), xar_linuxattr_read,&context) < 0) {
+ rc = XAR(x)->attrcopy_to_heap(x, f, xar_ea_root(e), xar_linuxattr_read, &context);
+ if (context.buf != NULL)
+ free(context.buf);
+ if (rc < 0) {
retval = -1;
goto BAIL;
}
- free(context.buf);
context.attrname = NULL;
}
--
2.44.1
|