add configs/firefox-with-cloned-net.cfg
This commit is contained in:
parent
857b9901f5
commit
7b2fc9cdac
17
cmdline.c
17
cmdline.c
@ -225,10 +225,11 @@ void cmdlineLogParams(struct nsjconf_t *nsjconf)
|
||||
struct mounts_t *p;
|
||||
TAILQ_FOREACH(p, &nsjconf->mountpts, pointers) {
|
||||
LOG_I
|
||||
("Mount point: src:'%s' dst:'%s' type:'%s' flags:%s options:'%s' isDir:%s mandatory:%s",
|
||||
("Mount point: src:'%s' dst:'%s' type:'%s' flags:%s options:'%s' isDir:%s mandatory:%s src_content:%s (size:%zu)",
|
||||
p->src ? p->src : "[NULL]", p->dst, p->fs_type ? p->fs_type : "[NULL]",
|
||||
mountFlagsToStr(p->flags), p->options ? p->options : "[NULL]",
|
||||
p->isDir ? "true" : "false", p->mandatory ? "true" : "false");
|
||||
p->isDir ? "true" : "false", p->mandatory ? "true" : "false",
|
||||
p->src_content ? "true" : "false", p->src_content_len);
|
||||
}
|
||||
}
|
||||
{
|
||||
@ -606,6 +607,8 @@ bool cmdlineParse(int argc, char *argv[], struct nsjconf_t * nsjconf)
|
||||
case 'R':{
|
||||
struct mounts_t *p = utilMalloc(sizeof(struct mounts_t));
|
||||
p->src = optarg;
|
||||
p->src_content = NULL;
|
||||
p->src_content_len = 0;
|
||||
const char *dst = cmdlineSplitStrByColon(optarg);
|
||||
p->dst = dst ? dst : optarg;
|
||||
p->flags = MS_BIND | MS_REC | MS_RDONLY;
|
||||
@ -618,6 +621,8 @@ bool cmdlineParse(int argc, char *argv[], struct nsjconf_t * nsjconf)
|
||||
case 'B':{
|
||||
struct mounts_t *p = utilMalloc(sizeof(struct mounts_t));
|
||||
p->src = optarg;
|
||||
p->src_content = NULL;
|
||||
p->src_content_len = 0;
|
||||
const char *dst = cmdlineSplitStrByColon(optarg);
|
||||
p->dst = dst ? dst : optarg;
|
||||
p->flags = MS_BIND | MS_REC;
|
||||
@ -630,6 +635,8 @@ bool cmdlineParse(int argc, char *argv[], struct nsjconf_t * nsjconf)
|
||||
case 'T':{
|
||||
struct mounts_t *p = utilMalloc(sizeof(struct mounts_t));
|
||||
p->src = NULL;
|
||||
p->src_content = NULL;
|
||||
p->src_content_len = 0;
|
||||
p->dst = optarg;
|
||||
p->flags = 0;
|
||||
p->options = cmdlineTmpfsSz;
|
||||
@ -713,6 +720,8 @@ bool cmdlineParse(int argc, char *argv[], struct nsjconf_t * nsjconf)
|
||||
if (nsjconf->mount_proc == true) {
|
||||
struct mounts_t *p = utilMalloc(sizeof(struct mounts_t));
|
||||
p->src = NULL;
|
||||
p->src_content = NULL;
|
||||
p->src_content_len = 0;
|
||||
p->dst = "/proc";
|
||||
p->flags = 0;
|
||||
if (nsjconf->is_root_rw == false) {
|
||||
@ -727,6 +736,8 @@ bool cmdlineParse(int argc, char *argv[], struct nsjconf_t * nsjconf)
|
||||
if (nsjconf->chroot != NULL) {
|
||||
struct mounts_t *p = utilMalloc(sizeof(struct mounts_t));
|
||||
p->src = nsjconf->chroot;
|
||||
p->src_content = NULL;
|
||||
p->src_content_len = 0;
|
||||
p->dst = "/";
|
||||
p->flags = MS_BIND | MS_REC;
|
||||
if (nsjconf->is_root_rw == false) {
|
||||
@ -740,6 +751,8 @@ bool cmdlineParse(int argc, char *argv[], struct nsjconf_t * nsjconf)
|
||||
} else {
|
||||
struct mounts_t *p = utilMalloc(sizeof(struct mounts_t));
|
||||
p->src = NULL;
|
||||
p->src_content = NULL;
|
||||
p->src_content_len = 0;
|
||||
p->dst = "/";
|
||||
p->flags = 0;
|
||||
if (nsjconf->is_root_rw == false) {
|
||||
|
2
common.h
2
common.h
@ -66,6 +66,8 @@ struct pids_t {
|
||||
|
||||
struct mounts_t {
|
||||
const char *src;
|
||||
const uint8_t *src_content;
|
||||
size_t src_content_len;
|
||||
const char *dst;
|
||||
const char *fs_type;
|
||||
const char *options;
|
||||
|
9
config.c
9
config.c
@ -187,9 +187,16 @@ static bool configParseInternal(struct nsjconf_t *nsjconf, Nsjail__NsJailConfig
|
||||
const bool *isDir =
|
||||
(njc->mount[i]->has_is_dir) ? (const bool *)&njc->mount[i]->is_dir : NULL;
|
||||
|
||||
uint8_t *src_content = NULL;
|
||||
size_t src_content_len = 0;
|
||||
if (njc->mount[i]->has_src_content) {
|
||||
src_content = njc->mount[i]->src_content.data;
|
||||
src_content_len = njc->mount[i]->src_content.len;
|
||||
}
|
||||
|
||||
if (mountAddMountPt
|
||||
(nsjconf, src, dst, fstype, options, flags, isDir, mandatory, src_env,
|
||||
dst_env) == false) {
|
||||
dst_env, src_content, src_content_len) == false) {
|
||||
LOG_E("Couldn't add mountpoint for src:'%s' dst:'%s'", src, dst);
|
||||
return false;
|
||||
}
|
||||
|
@ -238,7 +238,7 @@ char nsjail__mount_pt__options__default_value[] = "";
|
||||
static const protobuf_c_boolean nsjail__mount_pt__is_bind__default_value = 0;
|
||||
static const protobuf_c_boolean nsjail__mount_pt__rw__default_value = 0;
|
||||
static const protobuf_c_boolean nsjail__mount_pt__mandatory__default_value = 1;
|
||||
static const ProtobufCFieldDescriptor nsjail__mount_pt__field_descriptors[10] = {
|
||||
static const ProtobufCFieldDescriptor nsjail__mount_pt__field_descriptors[11] = {
|
||||
{
|
||||
"src",
|
||||
1,
|
||||
@ -264,8 +264,20 @@ static const ProtobufCFieldDescriptor nsjail__mount_pt__field_descriptors[10] =
|
||||
0, NULL, NULL /* reserved1,reserved2, etc */
|
||||
},
|
||||
{
|
||||
"dst",
|
||||
"src_content",
|
||||
3,
|
||||
PROTOBUF_C_LABEL_OPTIONAL,
|
||||
PROTOBUF_C_TYPE_BYTES,
|
||||
offsetof(Nsjail__MountPt, has_src_content),
|
||||
offsetof(Nsjail__MountPt, src_content),
|
||||
NULL,
|
||||
NULL,
|
||||
0, /* flags */
|
||||
0, NULL, NULL /* reserved1,reserved2, etc */
|
||||
},
|
||||
{
|
||||
"dst",
|
||||
4,
|
||||
PROTOBUF_C_LABEL_REQUIRED,
|
||||
PROTOBUF_C_TYPE_STRING,
|
||||
0, /* quantifier_offset */
|
||||
@ -277,7 +289,7 @@ static const ProtobufCFieldDescriptor nsjail__mount_pt__field_descriptors[10] =
|
||||
},
|
||||
{
|
||||
"prefix_dst_env",
|
||||
4,
|
||||
5,
|
||||
PROTOBUF_C_LABEL_OPTIONAL,
|
||||
PROTOBUF_C_TYPE_STRING,
|
||||
0, /* quantifier_offset */
|
||||
@ -289,7 +301,7 @@ static const ProtobufCFieldDescriptor nsjail__mount_pt__field_descriptors[10] =
|
||||
},
|
||||
{
|
||||
"fstype",
|
||||
5,
|
||||
6,
|
||||
PROTOBUF_C_LABEL_OPTIONAL,
|
||||
PROTOBUF_C_TYPE_STRING,
|
||||
0, /* quantifier_offset */
|
||||
@ -301,7 +313,7 @@ static const ProtobufCFieldDescriptor nsjail__mount_pt__field_descriptors[10] =
|
||||
},
|
||||
{
|
||||
"options",
|
||||
6,
|
||||
7,
|
||||
PROTOBUF_C_LABEL_REQUIRED,
|
||||
PROTOBUF_C_TYPE_STRING,
|
||||
0, /* quantifier_offset */
|
||||
@ -313,7 +325,7 @@ static const ProtobufCFieldDescriptor nsjail__mount_pt__field_descriptors[10] =
|
||||
},
|
||||
{
|
||||
"is_bind",
|
||||
7,
|
||||
8,
|
||||
PROTOBUF_C_LABEL_REQUIRED,
|
||||
PROTOBUF_C_TYPE_BOOL,
|
||||
0, /* quantifier_offset */
|
||||
@ -325,7 +337,7 @@ static const ProtobufCFieldDescriptor nsjail__mount_pt__field_descriptors[10] =
|
||||
},
|
||||
{
|
||||
"rw",
|
||||
8,
|
||||
9,
|
||||
PROTOBUF_C_LABEL_REQUIRED,
|
||||
PROTOBUF_C_TYPE_BOOL,
|
||||
0, /* quantifier_offset */
|
||||
@ -337,7 +349,7 @@ static const ProtobufCFieldDescriptor nsjail__mount_pt__field_descriptors[10] =
|
||||
},
|
||||
{
|
||||
"is_dir",
|
||||
9,
|
||||
10,
|
||||
PROTOBUF_C_LABEL_OPTIONAL,
|
||||
PROTOBUF_C_TYPE_BOOL,
|
||||
offsetof(Nsjail__MountPt, has_is_dir),
|
||||
@ -349,7 +361,7 @@ static const ProtobufCFieldDescriptor nsjail__mount_pt__field_descriptors[10] =
|
||||
},
|
||||
{
|
||||
"mandatory",
|
||||
10,
|
||||
11,
|
||||
PROTOBUF_C_LABEL_REQUIRED,
|
||||
PROTOBUF_C_TYPE_BOOL,
|
||||
0, /* quantifier_offset */
|
||||
@ -362,21 +374,22 @@ static const ProtobufCFieldDescriptor nsjail__mount_pt__field_descriptors[10] =
|
||||
};
|
||||
|
||||
static const unsigned nsjail__mount_pt__field_indices_by_name[] = {
|
||||
2, /* field[2] = dst */
|
||||
4, /* field[4] = fstype */
|
||||
6, /* field[6] = is_bind */
|
||||
8, /* field[8] = is_dir */
|
||||
9, /* field[9] = mandatory */
|
||||
5, /* field[5] = options */
|
||||
3, /* field[3] = prefix_dst_env */
|
||||
3, /* field[3] = dst */
|
||||
5, /* field[5] = fstype */
|
||||
7, /* field[7] = is_bind */
|
||||
9, /* field[9] = is_dir */
|
||||
10, /* field[10] = mandatory */
|
||||
6, /* field[6] = options */
|
||||
4, /* field[4] = prefix_dst_env */
|
||||
1, /* field[1] = prefix_src_env */
|
||||
7, /* field[7] = rw */
|
||||
8, /* field[8] = rw */
|
||||
0, /* field[0] = src */
|
||||
2, /* field[2] = src_content */
|
||||
};
|
||||
|
||||
static const ProtobufCIntRange nsjail__mount_pt__number_ranges[1 + 1] = {
|
||||
{1, 0},
|
||||
{0, 10}
|
||||
{0, 11}
|
||||
};
|
||||
|
||||
const ProtobufCMessageDescriptor nsjail__mount_pt__descriptor = {
|
||||
@ -386,7 +399,7 @@ const ProtobufCMessageDescriptor nsjail__mount_pt__descriptor = {
|
||||
"Nsjail__MountPt",
|
||||
"nsjail",
|
||||
sizeof(Nsjail__MountPt),
|
||||
10,
|
||||
11,
|
||||
nsjail__mount_pt__field_descriptors,
|
||||
nsjail__mount_pt__field_indices_by_name,
|
||||
1, nsjail__mount_pt__number_ranges,
|
||||
|
@ -91,6 +91,11 @@ struct _Nsjail__MountPt {
|
||||
* Should 'src' path be prefixed with this envvar?
|
||||
*/
|
||||
char *prefix_src_env;
|
||||
/*
|
||||
* If specified, contains buffer that will be written to the dst file
|
||||
*/
|
||||
protobuf_c_boolean has_src_content;
|
||||
ProtobufCBinaryData src_content;
|
||||
/*
|
||||
* Mount point inside jail
|
||||
*/
|
||||
@ -130,7 +135,7 @@ extern char nsjail__mount_pt__fstype__default_value[];
|
||||
extern char nsjail__mount_pt__options__default_value[];
|
||||
#define NSJAIL__MOUNT_PT__INIT \
|
||||
{ PROTOBUF_C_MESSAGE_INIT (&nsjail__mount_pt__descriptor) \
|
||||
, NULL, NULL, NULL, NULL, nsjail__mount_pt__fstype__default_value, nsjail__mount_pt__options__default_value, 0, 0, 0,0, 1 }
|
||||
, NULL, NULL, 0,{0,NULL}, NULL, NULL, nsjail__mount_pt__fstype__default_value, nsjail__mount_pt__options__default_value, 0, 0, 0,0, 1 }
|
||||
|
||||
struct _Nsjail__Exe {
|
||||
ProtobufCMessage base;
|
||||
|
18
config.proto
18
config.proto
@ -32,23 +32,25 @@ message MountPt
|
||||
optional string src = 1;
|
||||
/* Should 'src' path be prefixed with this envvar? */
|
||||
optional string prefix_src_env = 2;
|
||||
/* If specified, contains buffer that will be written to the dst file */
|
||||
optional bytes src_content = 3;
|
||||
/* Mount point inside jail */
|
||||
required string dst = 3;
|
||||
required string dst = 4;
|
||||
/* Should 'dst' path be prefixed with this envvar? */
|
||||
optional string prefix_dst_env = 4;
|
||||
optional string prefix_dst_env = 5;
|
||||
/* Can be empty for mount --bind mounts */
|
||||
optional string fstype = 5 [ default = "" ];
|
||||
optional string fstype = 6 [ default = "" ];
|
||||
/* E.g. size=5000000 for 'tmpfs' */
|
||||
required string options = 6 [ default = "" ];
|
||||
required string options = 7 [ default = "" ];
|
||||
/* Is it 'mount --bind src dst' type of mount */
|
||||
required bool is_bind = 7 [ default = false ];
|
||||
required bool is_bind = 8 [ default = false ];
|
||||
/* It it R/W mount */
|
||||
required bool rw = 8 [ default = false ];
|
||||
required bool rw = 9 [ default = false ];
|
||||
/* Is it directory? If not specified an internal
|
||||
heuristics will be used to determine that */
|
||||
optional bool is_dir = 9;
|
||||
optional bool is_dir = 10;
|
||||
/* Should the sandboxing fail if we cannot mount this resource? */
|
||||
required bool mandatory = 10 [ default = true ];
|
||||
required bool mandatory = 11 [ default = true ];
|
||||
}
|
||||
message Exe
|
||||
{
|
||||
|
166
configs/firefox-with-cloned-net.cfg
Normal file
166
configs/firefox-with-cloned-net.cfg
Normal file
@ -0,0 +1,166 @@
|
||||
name: "firefox-with-cloned-net"
|
||||
description: "
|
||||
This policy allows to run firefox inside a jail on a separate eth interface.
|
||||
A separate networking context separates process from the global \"lo\", and
|
||||
from global abstract socket namespace.
|
||||
|
||||
The only permitted home directory is $HOME/.mozilla and $HOME/Documents.
|
||||
The rest of available on the FS files/dires are libs and X-related files/dirs.
|
||||
|
||||
As this needs to be run as root, you will have to set-up correct uid&gid
|
||||
mappings (here: 'jagger'), name of your local interface (here: 'enp0s31f6'),
|
||||
and correct IPv4 addresses.
|
||||
|
||||
IPv6 should work out-of-the-box, given that your local IPv6 discovery is set
|
||||
up correctly.
|
||||
|
||||
Run as:
|
||||
|
||||
sudo ./nsjail --config configs/firefox-with-cloned-net.cfg
|
||||
|
||||
You can then go to https://uploadfiles.io/ and try to upload a file in order
|
||||
to see how your local directory (also, all system directories) look like.
|
||||
"
|
||||
|
||||
mode: ONCE
|
||||
hostname: "FF-MACVTAP"
|
||||
cwd: "/user"
|
||||
|
||||
time_limit: 0
|
||||
|
||||
envar: "HOME=/user"
|
||||
envar: "DISPLAY=:0"
|
||||
envar: "TMP=/tmp"
|
||||
|
||||
rlimit_as: 4096
|
||||
rlimit_cpu: 1000
|
||||
rlimit_fsize: 1024
|
||||
rlimit_nofile: 128
|
||||
|
||||
uidmap {
|
||||
inside_id: "9999999"
|
||||
outside_id: "jagger"
|
||||
}
|
||||
|
||||
gidmap {
|
||||
inside_id: "9999999"
|
||||
outside_id: "jagger"
|
||||
}
|
||||
|
||||
mount {
|
||||
dst: "/proc"
|
||||
fstype: "proc"
|
||||
}
|
||||
|
||||
mount {
|
||||
src: "/lib"
|
||||
dst: "/lib"
|
||||
is_bind: true
|
||||
}
|
||||
|
||||
mount {
|
||||
src: "/usr/lib"
|
||||
dst: "/usr/lib"
|
||||
is_bind: true
|
||||
}
|
||||
|
||||
mount {
|
||||
src: "/lib64"
|
||||
dst: "/lib64"
|
||||
is_bind: true
|
||||
mandatory: false
|
||||
}
|
||||
|
||||
mount {
|
||||
src: "/lib32"
|
||||
dst: "/lib32"
|
||||
is_bind: true
|
||||
mandatory: false
|
||||
}
|
||||
|
||||
mount {
|
||||
src: "/usr/lib/firefox"
|
||||
dst: "/usr/lib/firefox"
|
||||
is_bind: true
|
||||
}
|
||||
|
||||
mount {
|
||||
src: "/usr/bin/firefox"
|
||||
dst: "/usr/bin/firefox"
|
||||
is_bind: true
|
||||
}
|
||||
|
||||
mount {
|
||||
src: "/usr/share"
|
||||
dst: "/usr/share"
|
||||
is_bind: true
|
||||
}
|
||||
|
||||
mount {
|
||||
src: "/dev/urandom"
|
||||
dst: "/dev/urandom"
|
||||
is_bind: true
|
||||
rw: true
|
||||
}
|
||||
|
||||
mount {
|
||||
src_content: "nameserver 8.8.8.8"
|
||||
dst: "/etc/resolv.conf"
|
||||
}
|
||||
|
||||
mount {
|
||||
dst: "/tmp"
|
||||
fstype: "tmpfs"
|
||||
rw: true
|
||||
is_bind: false
|
||||
}
|
||||
|
||||
mount {
|
||||
dst: "/user"
|
||||
fstype: "tmpfs"
|
||||
rw: true
|
||||
}
|
||||
|
||||
mount {
|
||||
prefix_src_env: "HOME"
|
||||
src: "/Documents"
|
||||
dst: "/user/Documents"
|
||||
rw: true
|
||||
is_bind: true
|
||||
mandatory: false
|
||||
}
|
||||
|
||||
mount {
|
||||
prefix_src_env: "HOME"
|
||||
src: "/.mozilla"
|
||||
dst: "/user/.mozilla"
|
||||
is_bind: true
|
||||
rw: true
|
||||
mandatory: false
|
||||
}
|
||||
|
||||
mount {
|
||||
src: "/tmp/.X11-unix/X0"
|
||||
dst: "/tmp/.X11-unix/X0"
|
||||
is_bind: true
|
||||
}
|
||||
|
||||
seccomp_string: "
|
||||
POLICY example {
|
||||
KILL {
|
||||
ptrace,
|
||||
process_vm_readv,
|
||||
process_vm_writev
|
||||
}
|
||||
}
|
||||
USE example DEFAULT ALLOW
|
||||
"
|
||||
|
||||
macvlan_iface: "enp0s31f6"
|
||||
macvlan_vs_ip: "192.168.10.223"
|
||||
macvlan_vs_nm: "255.255.255.0"
|
||||
macvlan_vs_gw: "192.168.10.1"
|
||||
|
||||
exec_bin {
|
||||
path: "/usr/lib/firefox/firefox"
|
||||
}
|
29
mount.c
29
mount.c
@ -152,6 +152,23 @@ static bool mountMount(struct mounts_t *mpt, const char *oldroot, const char *ds
|
||||
}
|
||||
}
|
||||
|
||||
if (mpt->src_content) {
|
||||
snprintf(srcpath, sizeof(srcpath), "/file.XXXXXX");
|
||||
int fd = mkostemp(srcpath, O_CLOEXEC);
|
||||
if (fd < 0) {
|
||||
PLOG_W("mkostemp('%s')", srcpath);
|
||||
close(fd);
|
||||
return false;
|
||||
}
|
||||
if (utilWriteToFd(fd, mpt->src_content, mpt->src_content_len) == false) {
|
||||
LOG_W("Writting %zu bytes to '%s' failed", mpt->src_content_len, srcpath);
|
||||
close(fd);
|
||||
return false;
|
||||
}
|
||||
close(fd);
|
||||
mpt->flags |= (MS_BIND | MS_REC);
|
||||
}
|
||||
|
||||
/*
|
||||
* Initially mount it as RW, it will be remounted later on if needed
|
||||
*/
|
||||
@ -343,7 +360,8 @@ bool mountInitNs(struct nsjconf_t * nsjconf)
|
||||
|
||||
bool mountAddMountPt(struct nsjconf_t * nsjconf, const char *src, const char *dst,
|
||||
const char *fstype, const char *options, uintptr_t flags, const bool * isDir,
|
||||
bool mandatory, const char *src_env, const char *dst_env)
|
||||
bool mandatory, const char *src_env, const char *dst_env,
|
||||
const uint8_t * src_content, size_t src_content_len)
|
||||
{
|
||||
struct mounts_t *p = utilCalloc(sizeof(struct mounts_t));
|
||||
|
||||
@ -393,13 +411,15 @@ bool mountAddMountPt(struct nsjconf_t * nsjconf, const char *src, const char *ds
|
||||
p->fs_type = utilStrDup(fstype);
|
||||
p->options = utilStrDup(options);
|
||||
p->flags = flags;
|
||||
p->isDir = isDir;
|
||||
p->isDir = true;
|
||||
p->mandatory = mandatory;
|
||||
|
||||
if (isDir) {
|
||||
p->isDir = *isDir;
|
||||
} else {
|
||||
if (p->src == NULL) {
|
||||
if (src_content) {
|
||||
p->isDir = false;
|
||||
} else if (p->src == NULL) {
|
||||
p->isDir = true;
|
||||
} else if (p->flags & MS_BIND) {
|
||||
p->isDir = mountIsDir(p->src);
|
||||
@ -408,6 +428,9 @@ bool mountAddMountPt(struct nsjconf_t * nsjconf, const char *src, const char *ds
|
||||
}
|
||||
}
|
||||
|
||||
p->src_content = utilMemDup(src_content, src_content_len);
|
||||
p->src_content_len = src_content_len;
|
||||
|
||||
TAILQ_INSERT_TAIL(&nsjconf->mountpts, p, pointers);
|
||||
|
||||
return true;
|
||||
|
3
mount.h
3
mount.h
@ -31,6 +31,7 @@ bool mountIsDir(const char *path);
|
||||
bool mountInitNs(struct nsjconf_t *nsjconf);
|
||||
bool mountAddMountPt(struct nsjconf_t *nsjconf, const char *src, const char *dst,
|
||||
const char *fstype, const char *options, uintptr_t flags, const bool * isDir,
|
||||
bool mandatory, const char *src_env, const char *dst_env);
|
||||
bool mandatory, const char *src_env, const char *dst_env,
|
||||
const uint8_t * src_content, size_t src_content_len);
|
||||
|
||||
#endif /* NS_MOUNT_H */
|
||||
|
10
util.c
10
util.c
@ -70,6 +70,16 @@ char *utilStrDupLen(const char *str, size_t len)
|
||||
return ret;
|
||||
}
|
||||
|
||||
uint8_t *utilMemDup(const uint8_t * src, size_t len)
|
||||
{
|
||||
if (src == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
uint8_t *ret = utilMalloc(len);
|
||||
memcpy(ret, src, len);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ssize_t utilReadFromFd(int fd, void *buf, size_t len)
|
||||
{
|
||||
uint8_t *charbuf = (uint8_t *) buf;
|
||||
|
1
util.h
1
util.h
@ -30,6 +30,7 @@
|
||||
void *utilMalloc(size_t sz);
|
||||
void *utilCalloc(size_t sz);
|
||||
char *utilStrDup(const char *str);
|
||||
uint8_t *utilMemDup(const uint8_t * src, size_t len);
|
||||
ssize_t utilReadFromFd(int fd, void *buf, size_t len);
|
||||
ssize_t utilReadFromFile(const char *fname, void *buf, size_t len);
|
||||
ssize_t utilWriteToFd(int fd, const void *buf, size_t len);
|
||||
|
Loading…
Reference in New Issue
Block a user