summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.am4
-rw-r--r--src/Makefile.in96
-rw-r--r--src/apprentice.c154
-rw-r--r--src/ascmagic.c29
-rw-r--r--src/buffer.c84
-rw-r--r--src/cdf.c23
-rw-r--r--src/compress.c8
-rw-r--r--src/encoding.c16
-rw-r--r--src/file.c174
-rw-r--r--src/file.h66
-rw-r--r--src/file_opts.h3
-rw-r--r--src/funcs.c27
-rw-r--r--src/is_tar.c12
-rw-r--r--src/readcdf.c8
-rw-r--r--src/readelf.c44
-rw-r--r--src/seccomp.c246
-rw-r--r--src/softmagic.c273
17 files changed, 936 insertions, 331 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index 155aec44ee67..bbd3f5016d5c 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -7,7 +7,7 @@ bin_PROGRAMS = file
AM_CPPFLAGS = -DMAGIC='"$(MAGIC)"'
AM_CFLAGS = $(CFLAG_VISIBILITY) @WARNINGS@
-libmagic_la_SOURCES = magic.c apprentice.c softmagic.c ascmagic.c \
+libmagic_la_SOURCES = buffer.c magic.c apprentice.c softmagic.c ascmagic.c \
encoding.c compress.c is_tar.c readelf.c print.c fsmagic.c \
funcs.c file.h readelf.h tar.h apptype.c der.c der.h \
file_opts.h elfclass.h mygetopt.h cdf.c cdf_time.c readcdf.c cdf.h
@@ -19,7 +19,7 @@ MINGWLIBS =
endif
libmagic_la_LIBADD = $(LTLIBOBJS) $(MINGWLIBS)
-file_SOURCES = file.c
+file_SOURCES = file.c seccomp.c
file_LDADD = libmagic.la
CLEANFILES = magic.h
EXTRA_DIST = magic.h.in
diff --git a/src/Makefile.in b/src/Makefile.in
index b6eeb20096bc..c096c71ea477 100644
--- a/src/Makefile.in
+++ b/src/Makefile.in
@@ -1,7 +1,7 @@
-# Makefile.in generated by automake 1.15 from Makefile.am.
+# Makefile.in generated by automake 1.13.1 from Makefile.am.
# @configure_input@
-# Copyright (C) 1994-2014 Free Software Foundation, Inc.
+# Copyright (C) 1994-2012 Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
@@ -17,61 +17,23 @@
VPATH = @srcdir@
-am__is_gnu_make = { \
- if test -z '$(MAKELEVEL)'; then \
- false; \
- elif test -n '$(MAKE_HOST)'; then \
- true; \
- elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
- true; \
- else \
- false; \
- fi; \
-}
-am__make_running_with_option = \
- case $${target_option-} in \
- ?) ;; \
- *) echo "am__make_running_with_option: internal error: invalid" \
- "target option '$${target_option-}' specified" >&2; \
- exit 1;; \
- esac; \
- has_opt=no; \
- sane_makeflags=$$MAKEFLAGS; \
- if $(am__is_gnu_make); then \
- sane_makeflags=$$MFLAGS; \
- else \
+am__make_dryrun = \
+ { \
+ am__dry=no; \
case $$MAKEFLAGS in \
*\\[\ \ ]*) \
- bs=\\; \
- sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
- | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \
- esac; \
- fi; \
- skip_next=no; \
- strip_trailopt () \
- { \
- flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
- }; \
- for flg in $$sane_makeflags; do \
- test $$skip_next = yes && { skip_next=no; continue; }; \
- case $$flg in \
- *=*|--*) continue;; \
- -*I) strip_trailopt 'I'; skip_next=yes;; \
- -*I?*) strip_trailopt 'I';; \
- -*O) strip_trailopt 'O'; skip_next=yes;; \
- -*O?*) strip_trailopt 'O';; \
- -*l) strip_trailopt 'l'; skip_next=yes;; \
- -*l?*) strip_trailopt 'l';; \
- -[dEDm]) skip_next=yes;; \
- -[JT]) skip_next=yes;; \
+ echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \
+ | grep '^AM OK$$' >/dev/null || am__dry=yes;; \
+ *) \
+ for am__flg in $$MAKEFLAGS; do \
+ case $$am__flg in \
+ *=*|--*) ;; \
+ *n*) am__dry=yes; break;; \
+ esac; \
+ done;; \
esac; \
- case $$flg in \
- *$$target_option*) has_opt=yes; break;; \
- esac; \
- done; \
- test $$has_opt = yes
-am__make_dryrun = (target_option=n; $(am__make_running_with_option))
-am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
+ test $$am__dry = yes; \
+ }
pkgincludedir = $(includedir)/@PACKAGE@
pkglibdir = $(libdir)/@PACKAGE@
pkglibexecdir = $(libexecdir)/@PACKAGE@
@@ -91,6 +53,10 @@ build_triplet = @build@
host_triplet = @host@
bin_PROGRAMS = file$(EXEEXT)
subdir = src
+DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am asprintf.c \
+ getopt_long.c localtime_r.c ctime_r.c getline.c pread.c \
+ strcasestr.c dprintf.c fmtcheck.c strlcpy.c asctime_r.c \
+ gmtime_r.c strlcat.c vasprintf.c $(top_srcdir)/depcomp
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \
$(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \
@@ -98,7 +64,6 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \
$(top_srcdir)/acinclude.m4 $(top_srcdir)/configure.ac
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
$(ACLOCAL_M4)
-DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
mkinstalldirs = $(install_sh) -d
CONFIG_HEADER = $(top_builddir)/config.h
CONFIG_CLEAN_FILES =
@@ -135,7 +100,7 @@ am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(bindir)" \
LTLIBRARIES = $(lib_LTLIBRARIES)
am__DEPENDENCIES_1 =
libmagic_la_DEPENDENCIES = $(LTLIBOBJS) $(am__DEPENDENCIES_1)
-am_libmagic_la_OBJECTS = magic.lo apprentice.lo softmagic.lo \
+am_libmagic_la_OBJECTS = buffer.lo magic.lo apprentice.lo softmagic.lo \
ascmagic.lo encoding.lo compress.lo is_tar.lo readelf.lo \
print.lo fsmagic.lo funcs.lo apptype.lo der.lo cdf.lo \
cdf_time.lo readcdf.lo
@@ -148,7 +113,7 @@ libmagic_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
$(libmagic_la_LDFLAGS) $(LDFLAGS) -o $@
PROGRAMS = $(bin_PROGRAMS)
-am_file_OBJECTS = file.$(OBJEXT)
+am_file_OBJECTS = file.$(OBJEXT) seccomp.$(OBJEXT)
file_OBJECTS = $(am_file_OBJECTS)
file_DEPENDENCIES = libmagic.la
AM_V_P = $(am__v_P_@AM_V@)
@@ -212,10 +177,6 @@ am__define_uniq_tagged_files = \
done | $(am__uniquify_input)`
ETAGS = etags
CTAGS = ctags
-am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp \
- asctime_r.c asprintf.c ctime_r.c dprintf.c fmtcheck.c \
- getline.c getopt_long.c gmtime_r.c localtime_r.c pread.c \
- strcasestr.c strlcat.c strlcpy.c vasprintf.c
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
pkgdatadir = @pkgdatadir@
ACLOCAL = @ACLOCAL@
@@ -229,7 +190,6 @@ AWK = @AWK@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
CFLAGS = @CFLAGS@
-CFLAG_VISIBILITY = @CFLAG_VISIBILITY@
CPP = @CPP@
CPPFLAGS = @CPPFLAGS@
CYGPATH_W = @CYGPATH_W@
@@ -245,7 +205,6 @@ EGREP = @EGREP@
EXEEXT = @EXEEXT@
FGREP = @FGREP@
GREP = @GREP@
-HAVE_VISIBILITY = @HAVE_VISIBILITY@
INSTALL = @INSTALL@
INSTALL_DATA = @INSTALL_DATA@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
@@ -342,7 +301,7 @@ lib_LTLIBRARIES = libmagic.la
nodist_include_HEADERS = magic.h
AM_CPPFLAGS = -DMAGIC='"$(MAGIC)"'
AM_CFLAGS = $(CFLAG_VISIBILITY) @WARNINGS@
-libmagic_la_SOURCES = magic.c apprentice.c softmagic.c ascmagic.c \
+libmagic_la_SOURCES = buffer.c magic.c apprentice.c softmagic.c ascmagic.c \
encoding.c compress.c is_tar.c readelf.c print.c fsmagic.c \
funcs.c file.h readelf.h tar.h apptype.c der.c der.h \
file_opts.h elfclass.h mygetopt.h cdf.c cdf_time.c readcdf.c cdf.h
@@ -351,7 +310,7 @@ libmagic_la_LDFLAGS = -no-undefined -version-info 1:0:0
@MINGW_FALSE@MINGWLIBS =
@MINGW_TRUE@MINGWLIBS = -lgnurx -lshlwapi
libmagic_la_LIBADD = $(LTLIBOBJS) $(MINGWLIBS)
-file_SOURCES = file.c
+file_SOURCES = file.c seccomp.c
file_LDADD = libmagic.la
CLEANFILES = magic.h
EXTRA_DIST = magic.h.in
@@ -374,6 +333,7 @@ $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/Makefile'; \
$(am__cd) $(top_srcdir) && \
$(AUTOMAKE) --foreign src/Makefile
+.PRECIOUS: Makefile
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
@case '$?' in \
*config.status*) \
@@ -426,7 +386,6 @@ clean-libLTLIBRARIES:
echo rm -f $${locs}; \
rm -f $${locs}; \
}
-
libmagic.la: $(libmagic_la_OBJECTS) $(libmagic_la_DEPENDENCIES) $(EXTRA_libmagic_la_DEPENDENCIES)
$(AM_V_CCLD)$(libmagic_la_LINK) -rpath $(libdir) $(libmagic_la_OBJECTS) $(libmagic_la_LIBADD) $(LIBS)
install-binPROGRAMS: $(bin_PROGRAMS)
@@ -478,7 +437,6 @@ clean-binPROGRAMS:
list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \
echo " rm -f" $$list; \
rm -f $$list
-
file$(EXEEXT): $(file_OBJECTS) $(file_DEPENDENCIES) $(EXTRA_file_DEPENDENCIES)
@rm -f file$(EXEEXT)
$(AM_V_CCLD)$(LINK) $(file_OBJECTS) $(file_LDADD) $(LIBS)
@@ -506,6 +464,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/apprentice.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/apptype.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ascmagic.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/buffer.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cdf.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cdf_time.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/compress.Plo@am__quote@
@@ -519,6 +478,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/print.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/readcdf.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/readelf.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/seccomp.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/softmagic.Plo@am__quote@
.c.o:
@@ -788,8 +748,6 @@ uninstall-am: uninstall-binPROGRAMS uninstall-libLTLIBRARIES \
tags tags-am uninstall uninstall-am uninstall-binPROGRAMS \
uninstall-libLTLIBRARIES uninstall-nodist_includeHEADERS
-.PRECIOUS: Makefile
-
magic.h: ${HDR}
sed -e "s/X.YY/$$(echo @VERSION@ | tr -d .)/" < ${HDR} > $@
diff --git a/src/apprentice.c b/src/apprentice.c
index a7b4dd8f9115..e2ce2d3ad2ff 100644
--- a/src/apprentice.c
+++ b/src/apprentice.c
@@ -32,7 +32,7 @@
#include "file.h"
#ifndef lint
-FILE_RCSID("@(#)$File: apprentice.c,v 1.262 2017/08/28 13:39:18 christos Exp $")
+FILE_RCSID("@(#)$File: apprentice.c,v 1.270 2018/02/21 21:26:48 christos Exp $")
#endif /* lint */
#include "magic.h"
@@ -652,7 +652,7 @@ protected int
file_apprentice(struct magic_set *ms, const char *fn, int action)
{
char *p, *mfn;
- int file_err, errs = -1;
+ int fileerr, errs = -1;
size_t i;
(void)file_reset(ms, 0);
@@ -687,8 +687,8 @@ file_apprentice(struct magic_set *ms, const char *fn, int action)
*p++ = '\0';
if (*fn == '\0')
break;
- file_err = apprentice_1(ms, fn, action);
- errs = MAX(errs, file_err);
+ fileerr = apprentice_1(ms, fn, action);
+ errs = MAX(errs, fileerr);
fn = p;
}
@@ -1910,12 +1910,23 @@ parse(struct magic_set *ms, struct magic_entry *me, const char *line,
}
/* get offset, then skip over it */
- m->offset = (uint32_t)strtoul(l, &t, 0);
+ m->offset = (int32_t)strtol(l, &t, 0);
if (l == t) {
if (ms->flags & MAGIC_CHECK)
file_magwarn(ms, "offset `%s' invalid", l);
return -1;
}
+#if 0
+ if (m->offset < 0 && cont_level != 0 &&
+ (m->flag & (OFFADD | INDIROFFADD)) == 0) {
+ if (ms->flags & MAGIC_CHECK) {
+ file_magwarn(ms,
+ "negative direct offset `%s' at level %u",
+ l, cont_level);
+ }
+ return -1;
+ }
+#endif
l = t;
if (m->flag & INDIR) {
@@ -2337,7 +2348,7 @@ parse_ext(struct magic_set *ms, struct magic_entry *me, const char *line)
return parse_extra(ms, me, line,
CAST(off_t, offsetof(struct magic, ext)),
- sizeof(m->ext), "EXTENSION", ",!+-/@", 0);
+ sizeof(m->ext), "EXTENSION", ",!+-/@?_$", 0);
}
/*
@@ -2351,7 +2362,7 @@ parse_mime(struct magic_set *ms, struct magic_entry *me, const char *line)
return parse_extra(ms, me, line,
CAST(off_t, offsetof(struct magic, mimetype)),
- sizeof(m->mimetype), "MIME", "+-/.", 1);
+ sizeof(m->mimetype), "MIME", "+-/.$?:{}", 1);
}
private int
@@ -2608,6 +2619,9 @@ check_format(struct magic_set *ms, struct magic *m)
private int
getvalue(struct magic_set *ms, struct magic *m, const char **p, int action)
{
+ char *ep;
+ uint64_t ull;
+
switch (m->type) {
case FILE_BESTRING16:
case FILE_LESTRING16:
@@ -2636,79 +2650,78 @@ getvalue(struct magic_set *ms, struct magic *m, const char **p, int action)
return rc ? -1 : 0;
}
return 0;
+ default:
+ if (m->reln == 'x')
+ return 0;
+ break;
+ }
+
+ switch (m->type) {
case FILE_FLOAT:
case FILE_BEFLOAT:
case FILE_LEFLOAT:
- if (m->reln != 'x') {
- char *ep;
- errno = 0;
+ errno = 0;
#ifdef HAVE_STRTOF
- m->value.f = strtof(*p, &ep);
+ m->value.f = strtof(*p, &ep);
#else
- m->value.f = (float)strtod(*p, &ep);
+ m->value.f = (float)strtod(*p, &ep);
#endif
- if (errno == 0)
- *p = ep;
- }
+ if (errno == 0)
+ *p = ep;
return 0;
case FILE_DOUBLE:
case FILE_BEDOUBLE:
case FILE_LEDOUBLE:
- if (m->reln != 'x') {
- char *ep;
- errno = 0;
- m->value.d = strtod(*p, &ep);
- if (errno == 0)
- *p = ep;
- }
+ errno = 0;
+ m->value.d = strtod(*p, &ep);
+ if (errno == 0)
+ *p = ep;
return 0;
default:
- if (m->reln != 'x') {
- char *ep;
- uint64_t ull;
- errno = 0;
- ull = (uint64_t)strtoull(*p, &ep, 0);
- m->value.q = file_signextend(ms, m, ull);
- if (*p == ep) {
- file_magwarn(ms, "Unparseable number `%s'", *p);
- } else {
- size_t ts = typesize(m->type);
- uint64_t x;
- const char *q;
-
- if (ts == (size_t)~0) {
- file_magwarn(ms, "Expected numeric type got `%s'",
- type_tbl[m->type].name);
- }
- for (q = *p; isspace((unsigned char)*q); q++)
- continue;
- if (*q == '-')
- ull = -(int64_t)ull;
- switch (ts) {
- case 1:
- x = ull & ~0xffULL;
- break;
- case 2:
- x = ull & ~0xffffULL;
- break;
- case 4:
- x = ull & ~0xffffffffULL;
- break;
- case 8:
- x = 0;
- break;
- default:
- abort();
- }
- if (x) {
- file_magwarn(ms, "Overflow for numeric type `%s' value %#" PRIx64,
- type_tbl[m->type].name, ull);
- }
+ errno = 0;
+ ull = (uint64_t)strtoull(*p, &ep, 0);
+ m->value.q = file_signextend(ms, m, ull);
+ if (*p == ep) {
+ file_magwarn(ms, "Unparseable number `%s'", *p);
+ } else {
+ size_t ts = typesize(m->type);
+ uint64_t x;
+ const char *q;
+
+ if (ts == (size_t)~0) {
+ file_magwarn(ms,
+ "Expected numeric type got `%s'",
+ type_tbl[m->type].name);
}
- if (errno == 0) {
- *p = ep;
- eatsize(p);
+ for (q = *p; isspace((unsigned char)*q); q++)
+ continue;
+ if (*q == '-')
+ ull = -(int64_t)ull;
+ switch (ts) {
+ case 1:
+ x = (uint64_t)(ull & ~0xffULL);
+ break;
+ case 2:
+ x = (uint64_t)(ull & ~0xffffULL);
+ break;
+ case 4:
+ x = (uint64_t)(ull & ~0xffffffffULL);
+ break;
+ case 8:
+ x = 0;
+ break;
+ default:
+ abort();
}
+ if (x) {
+ file_magwarn(ms, "Overflow for numeric"
+ " type `%s' value %#" PRIx64,
+ type_tbl[m->type].name, ull);
+ }
+ }
+ if (errno == 0) {
+ *p = ep;
+ eatsize(p);
}
return 0;
}
@@ -3175,20 +3188,21 @@ apprentice_compile(struct magic_set *ms, struct magic_map *map, const char *fn)
if (write(fd, &hdr, sizeof(hdr)) != (ssize_t)sizeof(hdr)) {
file_error(ms, errno, "error writing `%s'", dbname);
- goto out;
+ goto out2;
}
for (i = 0; i < MAGIC_SETS; i++) {
len = m * map->nmagic[i];
if (write(fd, map->magic[i], len) != (ssize_t)len) {
file_error(ms, errno, "error writing `%s'", dbname);
- goto out;
+ goto out2;
}
}
+ rv = 0;
+out2:
if (fd != -1)
(void)close(fd);
- rv = 0;
out:
apprentice_unmap(map);
free(dbname);
@@ -3321,7 +3335,7 @@ private void
bs1(struct magic *m)
{
m->cont_level = swap2(m->cont_level);
- m->offset = swap4((uint32_t)m->offset);
+ m->offset = swap4((int32_t)m->offset);
m->in_offset = swap4((uint32_t)m->in_offset);
m->lineno = swap4((uint32_t)m->lineno);
if (IS_STRING(m->type)) {
diff --git a/src/ascmagic.c b/src/ascmagic.c
index 85a973e4fe2e..2d1abe543e60 100644
--- a/src/ascmagic.c
+++ b/src/ascmagic.c
@@ -35,7 +35,7 @@
#include "file.h"
#ifndef lint
-FILE_RCSID("@(#)$File: ascmagic.c,v 1.97 2016/06/27 20:56:25 christos Exp $")
+FILE_RCSID("@(#)$File: ascmagic.c,v 1.98 2017/11/02 20:25:39 christos Exp $")
#endif /* lint */
#include "magic.h"
@@ -68,26 +68,27 @@ trim_nuls(const unsigned char *buf, size_t nbytes)
}
protected int
-file_ascmagic(struct magic_set *ms, const unsigned char *buf, size_t nbytes,
- int text)
+file_ascmagic(struct magic_set *ms, const struct buffer *b, int text)
{
unichar *ubuf = NULL;
size_t ulen = 0;
int rv = 1;
+ struct buffer bb;
const char *code = NULL;
const char *code_mime = NULL;
const char *type = NULL;
- nbytes = trim_nuls(buf, nbytes);
+ bb = *b;
+ bb.flen = trim_nuls(b->fbuf, b->flen);
/* If file doesn't look like any sort of text, give up. */
- if (file_encoding(ms, buf, nbytes, &ubuf, &ulen, &code, &code_mime,
+ if (file_encoding(ms, &bb, &ubuf, &ulen, &code, &code_mime,
&type) == 0)
rv = 0;
else
- rv = file_ascmagic_with_encoding(ms, buf, nbytes, ubuf, ulen, code,
- type, text);
+ rv = file_ascmagic_with_encoding(ms, &bb,
+ ubuf, ulen, code, type, text);
free(ubuf);
@@ -95,10 +96,13 @@ file_ascmagic(struct magic_set *ms, const unsigned char *buf, size_t nbytes,
}
protected int
-file_ascmagic_with_encoding(struct magic_set *ms, const unsigned char *buf,
- size_t nbytes, unichar *ubuf, size_t ulen, const char *code,
+file_ascmagic_with_encoding(struct magic_set *ms,
+ const struct buffer *b, unichar *ubuf, size_t ulen, const char *code,
const char *type, int text)
{
+ struct buffer bb;
+ const unsigned char *buf = b->fbuf;
+ size_t nbytes = b->flen;
unsigned char *utf8_buf = NULL, *utf8_end;
size_t mlen, i;
int rv = -1;
@@ -140,10 +144,13 @@ file_ascmagic_with_encoding(struct magic_set *ms, const unsigned char *buf,
if ((utf8_end = encode_utf8(utf8_buf, mlen, ubuf, ulen))
== NULL)
goto done;
- if ((rv = file_softmagic(ms, utf8_buf,
- (size_t)(utf8_end - utf8_buf), NULL, NULL,
+ buffer_init(&bb, b->fd, utf8_buf,
+ (size_t)(utf8_end - utf8_buf));
+
+ if ((rv = file_softmagic(ms, &bb, NULL, NULL,
TEXTTEST, text)) == 0)
rv = -1;
+ buffer_fini(&bb);
if ((ms->flags & (MAGIC_APPLE|MAGIC_EXTENSION))) {
rv = rv == -1 ? 0 : 1;
goto done;
diff --git a/src/buffer.c b/src/buffer.c
new file mode 100644
index 000000000000..5f76b80d282c
--- /dev/null
+++ b/src/buffer.c
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) Christos Zoulas 2017.
+ * All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice immediately at the beginning of the file, without modification,
+ * this list of conditions, and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+#include "file.h"
+
+#ifndef lint
+FILE_RCSID("@(#)$File: buffer.c,v 1.4 2018/02/21 21:26:00 christos Exp $")
+#endif /* lint */
+
+#include "magic.h"
+#include <unistd.h>
+#include <string.h>
+#include <stdlib.h>
+#include <sys/stat.h>
+
+void
+buffer_init(struct buffer *b, int fd, const void *data, size_t len)
+{
+ b->fd = fd;
+ if (b->fd == -1 || fstat(b->fd, &b->st) == -1)
+ memset(&b->st, 0, sizeof(b->st));
+ b->fbuf = data;
+ b->flen = len;
+ b->eoff = 0;
+ b->ebuf = NULL;
+ b->elen = 0;
+}
+
+void
+buffer_fini(struct buffer *b)
+{
+ free(b->ebuf);
+}
+
+int
+buffer_fill(const struct buffer *bb)
+{
+ struct buffer *b = CCAST(struct buffer *, bb);
+
+ if (b->elen != 0)
+ return b->elen == (size_t)~0 ? -1 : 0;
+
+ if (!S_ISREG(b->st.st_mode))
+ goto out;
+
+ b->elen = (size_t)b->st.st_size < b->flen ?
+ (size_t)b->st.st_size : b->flen;
+ if ((b->ebuf = malloc(b->elen)) == NULL)
+ goto out;
+
+ b->eoff = b->st.st_size - b->elen;
+ if (pread(b->fd, b->ebuf, b->elen, b->eoff) == -1) {
+ free(b->ebuf);
+ goto out;
+ }
+
+ return 0;
+out:
+ b->elen = (size_t)~0;
+ return -1;
+}
diff --git a/src/cdf.c b/src/cdf.c
index accfb325b999..aad68cd0a33c 100644
--- a/src/cdf.c
+++ b/src/cdf.c
@@ -35,7 +35,7 @@
#include "file.h"
#ifndef lint
-FILE_RCSID("@(#)$File: cdf.c,v 1.106 2017/04/30 17:05:02 christos Exp $")
+FILE_RCSID("@(#)$File: cdf.c,v 1.110 2017/12/19 00:21:21 christos Exp $")
#endif
#include <assert.h>
@@ -85,6 +85,7 @@ static union {
#define CDF_CALLOC(n, u) cdf_calloc(__FILE__, __LINE__, (n), (u))
+/*ARGSUSED*/
static void *
cdf_malloc(const char *file __attribute__((__unused__)),
size_t line __attribute__((__unused__)), size_t n)
@@ -93,6 +94,7 @@ cdf_malloc(const char *file __attribute__((__unused__)),
return malloc(n);
}
+/*ARGSUSED*/
static void *
cdf_realloc(const char *file __attribute__((__unused__)),
size_t line __attribute__((__unused__)), void *p, size_t n)
@@ -101,6 +103,7 @@ cdf_realloc(const char *file __attribute__((__unused__)),
return realloc(p, n);
}
+/*ARGSUSED*/
static void *
cdf_calloc(const char *file __attribute__((__unused__)),
size_t line __attribute__((__unused__)), size_t n, size_t u)
@@ -436,7 +439,7 @@ cdf_read_sat(const cdf_info_t *info, cdf_header_t *h, cdf_sat_t *sat)
if (h->h_master_sat[i] == CDF_SECID_FREE)
break;
-#define CDF_SEC_LIMIT (UINT32_MAX / (8 * ss))
+#define CDF_SEC_LIMIT (UINT32_MAX / (64 * ss))
if ((nsatpersec > 0 &&
h->h_num_sectors_in_master_sat > CDF_SEC_LIMIT / nsatpersec) ||
i > CDF_SEC_LIMIT) {
@@ -846,8 +849,8 @@ cdf_find_stream(const cdf_dir_t *dir, const char *name, int type)
return 0;
}
-#define CDF_SHLEN_LIMIT (UINT32_MAX / 8)
-#define CDF_PROP_LIMIT (UINT32_MAX / (8 * sizeof(cdf_property_info_t)))
+#define CDF_SHLEN_LIMIT (UINT32_MAX / 64)
+#define CDF_PROP_LIMIT (UINT32_MAX / (64 * sizeof(cdf_property_info_t)))
static const void *
cdf_offset(const void *p, size_t l)
@@ -1570,32 +1573,32 @@ main(int argc, char *argv[])
info.i_len = 0;
for (i = 1; i < argc; i++) {
if ((info.i_fd = open(argv[1], O_RDONLY)) == -1)
- err(1, "Cannot open `%s'", argv[1]);
+ err(EXIT_FAILURE, "Cannot open `%s'", argv[1]);
if (cdf_read_header(&info, &h) == -1)
- err(1, "Cannot read header");
+ err(EXIT_FAILURE, "Cannot read header");
#ifdef CDF_DEBUG
cdf_dump_header(&h);
#endif
if (cdf_read_sat(&info, &h, &sat) == -1)
- err(1, "Cannot read sat");
+ err(EXIT_FAILURE, "Cannot read sat");
#ifdef CDF_DEBUG
cdf_dump_sat("SAT", &sat, CDF_SEC_SIZE(&h));
#endif
if (cdf_read_ssat(&info, &h, &sat, &ssat) == -1)
- err(1, "Cannot read ssat");
+ err(EXIT_FAILURE, "Cannot read ssat");
#ifdef CDF_DEBUG
cdf_dump_sat("SSAT", &ssat, CDF_SHORT_SEC_SIZE(&h));
#endif
if (cdf_read_dir(&info, &h, &sat, &dir) == -1)
- err(1, "Cannot read dir");
+ err(EXIT_FAILURE, "Cannot read dir");
if (cdf_read_short_stream(&info, &h, &sat, &dir, &sst, &root)
== -1)
- err(1, "Cannot read short stream");
+ err(EXIT_FAILURE, "Cannot read short stream");
#ifdef CDF_DEBUG
cdf_dump_stream(&sst);
#endif
diff --git a/src/compress.c b/src/compress.c
index 2f789cd2bc44..184011b92307 100644
--- a/src/compress.c
+++ b/src/compress.c
@@ -35,7 +35,7 @@
#include "file.h"
#ifndef lint
-FILE_RCSID("@(#)$File: compress.c,v 1.105 2017/05/25 00:13:03 christos Exp $")
+FILE_RCSID("@(#)$File: compress.c,v 1.106 2017/11/02 20:25:39 christos Exp $")
#endif
#include "magic.h"
@@ -184,8 +184,7 @@ static int makeerror(unsigned char **, size_t *, const char *, ...)
private const char *methodname(size_t);
protected int
-file_zmagic(struct magic_set *ms, int fd, const char *name,
- const unsigned char *buf, size_t nbytes)
+file_zmagic(struct magic_set *ms, const struct buffer *b, const char *name)
{
unsigned char *newbuf = NULL;
size_t i, nsz;
@@ -193,6 +192,9 @@ file_zmagic(struct magic_set *ms, int fd, const char *name,
file_pushbuf_t *pb;
int urv, prv, rv = 0;
int mime = ms->flags & MAGIC_MIME;
+ int fd = b->fd;
+ const unsigned char *buf = b->fbuf;
+ size_t nbytes = b->flen;
#ifdef HAVE_SIGNAL_H
sig_t osigpipe;
#endif
diff --git a/src/encoding.c b/src/encoding.c
index 3c116cd74f17..3e7b9e584b08 100644
--- a/src/encoding.c
+++ b/src/encoding.c
@@ -35,7 +35,7 @@
#include "file.h"
#ifndef lint
-FILE_RCSID("@(#)$File: encoding.c,v 1.13 2015/06/04 19:16:28 christos Exp $")
+FILE_RCSID("@(#)$File: encoding.c,v 1.14 2017/11/02 20:25:39 christos Exp $")
#endif /* lint */
#include "magic.h"
@@ -66,11 +66,21 @@ private void from_ebcdic(const unsigned char *, size_t, unsigned char *);
* ubuf, and the number of characters converted in ulen.
*/
protected int
-file_encoding(struct magic_set *ms, const unsigned char *buf, size_t nbytes, unichar **ubuf, size_t *ulen, const char **code, const char **code_mime, const char **type)
+file_encoding(struct magic_set *ms, const struct buffer *b, unichar **ubuf,
+ size_t *ulen, const char **code, const char **code_mime, const char **type)
{
+ const unsigned char *buf = b->fbuf;
+ size_t nbytes = b->flen;
size_t mlen;
int rv = 1, ucs_type;
unsigned char *nbuf = NULL;
+ unichar *udefbuf;
+ size_t udeflen;
+
+ if (ubuf == NULL)
+ ubuf = &udefbuf;
+ if (ulen == NULL)
+ ulen = &udeflen;
*type = "text";
*ulen = 0;
@@ -144,6 +154,8 @@ file_encoding(struct magic_set *ms, const unsigned char *buf, size_t nbytes, uni
done:
free(nbuf);
+ if (ubuf == &udefbuf)
+ free(udefbuf);
return rv;
}
diff --git a/src/file.c b/src/file.c
index fad3160d15fe..87dd1bb60f4c 100644
--- a/src/file.c
+++ b/src/file.c
@@ -32,7 +32,7 @@
#include "file.h"
#ifndef lint
-FILE_RCSID("@(#)$File: file.c,v 1.172 2016/10/24 15:21:07 christos Exp $")
+FILE_RCSID("@(#)$File: file.c,v 1.175 2018/03/02 16:11:37 christos Exp $")
#endif /* lint */
#include "magic.h"
@@ -59,26 +59,38 @@ FILE_RCSID("@(#)$File: file.c,v 1.172 2016/10/24 15:21:07 christos Exp $")
#endif
#if defined(HAVE_GETOPT_H) && defined(HAVE_STRUCT_OPTION)
-#include <getopt.h>
-#ifndef HAVE_GETOPT_LONG
-int getopt_long(int argc, char * const *argv, const char *optstring, const struct option *longopts, int *longindex);
+# include <getopt.h>
+# ifndef HAVE_GETOPT_LONG
+int getopt_long(int, char * const *, const char *,
+ const struct option *, int *);
+# endif
+# else
+# include "mygetopt.h"
#endif
+
+#ifdef S_IFLNK
+# define IFLNK_h "h"
+# define IFLNK_L "L"
#else
-#include "mygetopt.h"
+# define IFLNK_h ""
+# define IFLNK_L ""
#endif
-#ifdef S_IFLNK
-#define FILE_FLAGS "-bcEhikLlNnprsvzZ0"
+#ifdef HAVE_LIBSECCOMP
+# define SECCOMP_S "S"
#else
-#define FILE_FLAGS "-bcEiklNnprsvzZ0"
+# define SECCOMP_S ""
#endif
+#define FILE_FLAGS "bcCdE" IFLNK_h "ik" IFLNK_L "lNnprs" SECCOMP_S "vzZ0"
+#define OPTSTRING "bcCde:Ef:F:hiklLm:nNpP:rsSvzZ0"
+
# define USAGE \
- "Usage: %s [" FILE_FLAGS \
- "] [--apple] [--extension] [--mime-encoding] [--mime-type]\n" \
- " [-e testname] [-F separator] [-f namefile] [-m magicfiles] " \
- "file ...\n" \
- " %s -C [-m magicfiles]\n" \
+ "Usage: %s [-" FILE_FLAGS "] [--apple] [--extension] [--mime-encoding]\n" \
+ " [--mime-type] [-e <testname>] [-F <separator>] " \
+ " [-f <namefile>]\n" \
+ " [-m <magicfiles>] [-P <parameter=value>] <file> ...\n" \
+ " %s -C [-m <magicfiles>]\n" \
" %s [--help]\n"
private int /* Global command-line options */
@@ -102,8 +114,7 @@ private const struct option long_options[] = {
#undef OPT
#undef OPT_LONGONLY
{0, 0, NULL, 0}
-};
-#define OPTSTRING "bcCde:Ef:F:hiklLm:nNpP:rsvzZ0"
+ };
private const struct {
const char *name;
@@ -135,7 +146,6 @@ private struct {
{ "bytes", MAGIC_PARAM_BYTES_MAX, 0 },
};
-private char *progname; /* used throughout */
private int posixly;
#ifdef __dead
@@ -165,9 +175,13 @@ main(int argc, char *argv[])
size_t i;
int action = 0, didsomefiles = 0, errflg = 0;
int flags = 0, e = 0;
+#ifdef HAVE_LIBSECCOMP
+ int sandbox = 1;
+#endif
struct magic_set *magic = NULL;
int longindex;
const char *magicfile = NULL; /* where the magic is */
+ char *progname;
/* makes islower etc work for other langs */
#ifdef HAVE_SETLOCALE
@@ -184,6 +198,9 @@ main(int argc, char *argv[])
else
progname = argv[0];
+ file_setprogname(progname);
+
+
#ifdef S_IFLNK
posixly = getenv("POSIXLY_CORRECT") != NULL;
flags |= posixly ? MAGIC_SYMLINK : 0;
@@ -280,12 +297,18 @@ main(int argc, char *argv[])
case 's':
flags |= MAGIC_DEVICES;
break;
+#ifdef HAVE_LIBSECCOMP
+ case 'S':
+ sandbox = 0;
+ break;
+#endif
case 'v':
if (magicfile == NULL)
magicfile = magic_getpath(magicfile, action);
- (void)fprintf(stdout, "%s-%s\n", progname, VERSION);
+ (void)fprintf(stdout, "%s-%s\n", file_getprogname(),
+ VERSION);
(void)fprintf(stdout, "magic file from %s\n",
- magicfile);
+ magicfile);
return 0;
case 'z':
flags |= MAGIC_COMPRESS;
@@ -314,10 +337,19 @@ main(int argc, char *argv[])
if (e)
return e;
+#ifdef HAVE_LIBSECCOMP
+#if 0
+ if (sandbox && enable_sandbox_basic() == -1)
+#else
+ if (sandbox && enable_sandbox_full() == -1)
+#endif
+ file_err(EXIT_FAILURE, "SECCOMP initialisation failed");
+#endif /* HAVE_LIBSECCOMP */
+
if (MAGIC_VERSION != magic_version())
- (void)fprintf(stderr, "%s: compiled magic version [%d] "
+ file_warnx("Compiled magic version [%d] "
"does not match with shared library magic version [%d]\n",
- progname, MAGIC_VERSION, magic_version());
+ MAGIC_VERSION, magic_version());
switch(action) {
case FILE_CHECK:
@@ -329,8 +361,7 @@ main(int argc, char *argv[])
*/
magic = magic_open(flags|MAGIC_CHECK);
if (magic == NULL) {
- (void)fprintf(stderr, "%s: %s\n", progname,
- strerror(errno));
+ file_warn("Can't create magic");
return 1;
}
@@ -349,8 +380,7 @@ main(int argc, char *argv[])
abort();
}
if (c == -1) {
- (void)fprintf(stderr, "%s: %s\n", progname,
- magic_error(magic));
+ file_warnx("%s", magic_error(magic));
e = 1;
goto out;
}
@@ -398,11 +428,8 @@ applyparam(magic_t magic)
for (i = 0; i < __arraycount(pm); i++) {
if (pm[i].value == 0)
continue;
- if (magic_setparam(magic, pm[i].tag, &pm[i].value) == -1) {
- (void)fprintf(stderr, "%s: Can't set %s %s\n", progname,
- pm[i].name, strerror(errno));
- exit(1);
- }
+ if (magic_setparam(magic, pm[i].tag, &pm[i].value) == -1)
+ file_err(EXIT_FAILURE, "Can't set %s", pm[i].name);
}
}
@@ -422,8 +449,7 @@ setparam(const char *p)
return;
}
badparm:
- (void)fprintf(stderr, "%s: Unknown param %s\n", progname, p);
- exit(1);
+ file_errx(EXIT_FAILURE, "Unknown param %s", p);
}
private struct magic_set *
@@ -434,17 +460,16 @@ load(const char *magicfile, int flags)
const char *e;
if (magic == NULL) {
- (void)fprintf(stderr, "%s: %s\n", progname, strerror(errno));
+ file_warn("Can't create magic");
return NULL;
}
if (magic_load(magic, magicfile) == -1) {
- (void)fprintf(stderr, "%s: %s\n",
- progname, magic_error(magic));
+ file_warn("%s", magic_error(magic));
magic_close(magic);
return NULL;
}
if ((e = magic_error(magic)) != NULL)
- (void)fprintf(stderr, "%s: Warning: %s\n", progname, e);
+ file_warn("%s", e);
return magic;
}
@@ -466,8 +491,7 @@ unwrap(struct magic_set *ms, const char *fn)
wid = 1;
} else {
if ((f = fopen(fn, "r")) == NULL) {
- (void)fprintf(stderr, "%s: Cannot open `%s' (%s).\n",
- progname, fn, strerror(errno));
+ file_warn("Cannot open `%s'", fn);
return 1;
}
@@ -567,8 +591,9 @@ file_mbswidth(const char *s)
private void
usage(void)
{
- (void)fprintf(stderr, USAGE, progname, progname, progname);
- exit(1);
+ const char *pn = file_getprogname();
+ (void)fprintf(stderr, USAGE, pn, pn, pn);
+ exit(EXIT_FAILURE);
}
private void
@@ -629,5 +654,74 @@ help(void)
#undef OPT
#undef OPT_LONGONLY
fprintf(stdout, "\nReport bugs to http://bugs.gw.com/\n");
- exit(0);
+ exit(EXIT_SUCCESS);
+}
+
+private const char *file_progname;
+
+protected void
+file_setprogname(const char *progname)
+{
+ file_progname = progname;
+}
+
+protected const char *
+file_getprogname(void)
+{
+ return file_progname;
+}
+
+protected void
+file_err(int e, const char *fmt, ...)
+{
+ va_list ap;
+ int se = errno;
+
+ va_start(ap, fmt);
+ fprintf(stderr, "%s: ", file_progname);
+ vfprintf(stderr, fmt, ap);
+ va_end(ap);
+ fprintf(stderr, " (%s)\n", strerror(se));
+ exit(e);
+}
+
+protected void
+file_errx(int e, const char *fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ fprintf(stderr, "%s: ", file_progname);
+ vfprintf(stderr, fmt, ap);
+ va_end(ap);
+ fprintf(stderr, "\n");
+ exit(e);
+}
+
+protected void
+file_warn(const char *fmt, ...)
+{
+ va_list ap;
+ int se = errno;
+
+ va_start(ap, fmt);
+ fprintf(stderr, "%s: ", file_progname);
+ vfprintf(stderr, fmt, ap);
+ va_end(ap);
+ fprintf(stderr, " (%s)\n", strerror(se));
+ errno = se;
+}
+
+protected void
+file_warnx(const char *fmt, ...)
+{
+ va_list ap;
+ int se = errno;
+
+ va_start(ap, fmt);
+ fprintf(stderr, "%s: ", file_progname);
+ vfprintf(stderr, fmt, ap);
+ va_end(ap);
+ fprintf(stderr, "\n");
+ errno = se;
}
diff --git a/src/file.h b/src/file.h
index eb9c05421db6..66598bc6bb30 100644
--- a/src/file.h
+++ b/src/file.h
@@ -27,7 +27,7 @@
*/
/*
* file.h - definitions for file(1) program
- * @(#)$File: file.h,v 1.183 2017/08/28 13:39:18 christos Exp $
+ * @(#)$File: file.h,v 1.191 2018/02/21 21:26:00 christos Exp $
*/
#ifndef __file_h__
@@ -145,6 +145,16 @@
#define FILE_COMPILE 2
#define FILE_LIST 3
+struct buffer {
+ int fd;
+ struct stat st;
+ const void *fbuf;
+ size_t flen;
+ off_t eoff;
+ void *ebuf;
+ size_t elen;
+};
+
union VALUETYPE {
uint8_t b;
uint16_t h;
@@ -287,7 +297,7 @@ struct magic {
#endif /* ENABLE_CONDITIONALS */
/* Word 4 */
- uint32_t offset; /* offset to magic number */
+ int32_t offset; /* offset to magic number */
/* Word 5 */
int32_t in_offset; /* offset from indirection */
/* Word 6 */
@@ -394,7 +404,9 @@ struct magic_set {
char *buf; /* Accumulation buffer */
char *pbuf; /* Printable buffer */
} o;
- uint32_t offset;
+ uint32_t offset; /* a copy of m->offset while we */
+ /* are working on the magic entry */
+ uint32_t eoffset; /* offset from end of file */
int error;
int flags; /* Control magic tests. */
int event_flags; /* Note things that happened. */
@@ -448,23 +460,20 @@ protected int file_replace(struct magic_set *, const char *, const char *);
protected int file_printf(struct magic_set *, const char *, ...)
__attribute__((__format__(__printf__, 2, 3)));
protected int file_reset(struct magic_set *, int);
-protected int file_tryelf(struct magic_set *, int, const unsigned char *,
- size_t);
-protected int file_trycdf(struct magic_set *, int, const unsigned char *,
- size_t);
+protected int file_tryelf(struct magic_set *, const struct buffer *);
+protected int file_trycdf(struct magic_set *, const struct buffer *);
#if HAVE_FORK
-protected int file_zmagic(struct magic_set *, int, const char *,
- const unsigned char *, size_t);
+protected int file_zmagic(struct magic_set *, const struct buffer *,
+ const char *);
#endif
-protected int file_ascmagic(struct magic_set *, const unsigned char *, size_t,
+protected int file_ascmagic(struct magic_set *, const struct buffer *,
int);
protected int file_ascmagic_with_encoding(struct magic_set *,
- const unsigned char *, size_t, unichar *, size_t, const char *,
- const char *, int);
-protected int file_encoding(struct magic_set *, const unsigned char *, size_t,
+ const struct buffer *, unichar *, size_t, const char *, const char *, int);
+protected int file_encoding(struct magic_set *, const struct buffer *,
unichar **, size_t *, const char **, const char **, const char **);
-protected int file_is_tar(struct magic_set *, const unsigned char *, size_t);
-protected int file_softmagic(struct magic_set *, const unsigned char *, size_t,
+protected int file_is_tar(struct magic_set *, const struct buffer *);
+protected int file_softmagic(struct magic_set *, const struct buffer *,
uint16_t *, uint16_t *, int, int);
protected int file_apprentice(struct magic_set *, const char *, int);
protected int buffer_apprentice(struct magic_set *, struct magic **,
@@ -497,6 +506,10 @@ protected int file_os2_apptype(struct magic_set *, const char *, const void *,
size_t);
#endif /* __EMX__ */
+protected void buffer_init(struct buffer *, int, const void *, size_t);
+protected void buffer_fini(struct buffer *);
+protected int buffer_fill(const struct buffer *);
+
#if defined(HAVE_LOCALE_H)
#include <locale.h>
#endif
@@ -590,6 +603,29 @@ const char *fmtcheck(const char *, const char *)
__attribute__((__format_arg__(2)));
#endif
+#ifdef HAVE_LIBSECCOMP
+// basic filter
+// this mode should not interfere with normal operations
+// only some dangerous syscalls are blacklisted
+int enable_sandbox_basic(void);
+
+// enhanced filter
+// this mode allows only the necessary syscalls used during normal operation
+// extensive testing required !!!
+int enable_sandbox_full(void);
+#endif
+
+protected const char *file_getprogname(void);
+protected void file_setprogname(const char *);
+protected void file_err(int, const char *, ...)
+ __attribute__((__format__(__printf__, 2, 3)));
+protected void file_errx(int, const char *, ...)
+ __attribute__((__format__(__printf__, 2, 3)));
+protected void file_warn(const char *, ...)
+ __attribute__((__format__(__printf__, 1, 2)));
+protected void file_warnx(const char *, ...)
+ __attribute__((__format__(__printf__, 1, 2)));
+
#if defined(HAVE_MMAP) && defined(HAVE_SYS_MMAN_H) && !defined(QUICK)
#define QUICK
#endif
diff --git a/src/file_opts.h b/src/file_opts.h
index 52ace1893630..02611ccb8a85 100644
--- a/src/file_opts.h
+++ b/src/file_opts.h
@@ -54,5 +54,8 @@ OPT('P', "parameter", 1, 0, " set file engine parameter limits\n"
OPT('r', "raw", 0, 0, " don't translate unprintable chars to \\ooo\n")
OPT('s', "special-files", 0, 0, " treat special (block/char devices) files as\n"
" ordinary ones\n")
+#ifdef HAVE_LIBSECCOMP
+OPT('S', "no-sandbox", 0, 0, " disable system call sandboxing\n")
+#endif
OPT('C', "compile", 0, 0, " compile file specified by -m\n")
OPT('d', "debug", 0, 0, " print debugging messages\n")
diff --git a/src/funcs.c b/src/funcs.c
index d7a18f451a7e..f59f4a1b97dc 100644
--- a/src/funcs.c
+++ b/src/funcs.c
@@ -27,7 +27,7 @@
#include "file.h"
#ifndef lint
-FILE_RCSID("@(#)$File: funcs.c,v 1.93 2017/08/28 13:39:18 christos Exp $")
+FILE_RCSID("@(#)$File: funcs.c,v 1.94 2017/11/02 20:25:39 christos Exp $")
#endif /* lint */
#include "magic.h"
@@ -178,14 +178,14 @@ file_buffer(struct magic_set *ms, int fd, const char *inname __attribute__ ((__u
const void *buf, size_t nb)
{
int m = 0, rv = 0, looks_text = 0;
- const unsigned char *ubuf = CAST(const unsigned char *, buf);
- unichar *u8buf = NULL;
- size_t ulen;
const char *code = NULL;
const char *code_mime = "binary";
const char *type = "application/octet-stream";
const char *def = "data";
const char *ftype = NULL;
+ struct buffer b;
+
+ buffer_init(&b, fd, buf, nb);
if (nb == 0) {
def = "empty";
@@ -197,13 +197,13 @@ file_buffer(struct magic_set *ms, int fd, const char *inname __attribute__ ((__u
}
if ((ms->flags & MAGIC_NO_CHECK_ENCODING) == 0) {
- looks_text = file_encoding(ms, ubuf, nb, &u8buf, &ulen,
+ looks_text = file_encoding(ms, &b, NULL, 0,
&code, &code_mime, &ftype);
}
#ifdef __EMX__
if ((ms->flags & MAGIC_NO_CHECK_APPTYPE) == 0 && inname) {
- m = file_os2_apptype(ms, inname, buf, nb);
+ m = file_os2_apptype(ms, inname, &b);
if ((ms->flags & MAGIC_DEBUG) != 0)
(void)fprintf(stderr, "[try os2_apptype %d]\n", m);
switch (m) {
@@ -219,7 +219,7 @@ file_buffer(struct magic_set *ms, int fd, const char *inname __attribute__ ((__u
#if HAVE_FORK
/* try compression stuff */
if ((ms->flags & MAGIC_NO_CHECK_COMPRESS) == 0) {
- m = file_zmagic(ms, fd, inname, ubuf, nb);
+ m = file_zmagic(ms, &b, inname);
if ((ms->flags & MAGIC_DEBUG) != 0)
(void)fprintf(stderr, "[try zmagic %d]\n", m);
if (m) {
@@ -229,7 +229,7 @@ file_buffer(struct magic_set *ms, int fd, const char *inname __attribute__ ((__u
#endif
/* Check if we have a tar file */
if ((ms->flags & MAGIC_NO_CHECK_TAR) == 0) {
- m = file_is_tar(ms, ubuf, nb);
+ m = file_is_tar(ms, &b);
if ((ms->flags & MAGIC_DEBUG) != 0)
(void)fprintf(stderr, "[try tar %d]\n", m);
if (m) {
@@ -240,7 +240,7 @@ file_buffer(struct magic_set *ms, int fd, const char *inname __attribute__ ((__u
/* Check if we have a CDF file */
if ((ms->flags & MAGIC_NO_CHECK_CDF) == 0) {
- m = file_trycdf(ms, fd, ubuf, nb);
+ m = file_trycdf(ms, &b);
if ((ms->flags & MAGIC_DEBUG) != 0)
(void)fprintf(stderr, "[try cdf %d]\n", m);
if (m) {
@@ -251,8 +251,7 @@ file_buffer(struct magic_set *ms, int fd, const char *inname __attribute__ ((__u
/* try soft magic tests */
if ((ms->flags & MAGIC_NO_CHECK_SOFT) == 0) {
- m = file_softmagic(ms, ubuf, nb, NULL, NULL, BINTEST,
- looks_text);
+ m = file_softmagic(ms, &b, NULL, NULL, BINTEST, looks_text);
if ((ms->flags & MAGIC_DEBUG) != 0)
(void)fprintf(stderr, "[try softmagic %d]\n", m);
if (m) {
@@ -268,7 +267,7 @@ file_buffer(struct magic_set *ms, int fd, const char *inname __attribute__ ((__u
* ELF headers that cannot easily * be
* extracted with rules in the magic file.
*/
- m = file_tryelf(ms, fd, ubuf, nb);
+ m = file_tryelf(ms, &b);
if ((ms->flags & MAGIC_DEBUG) != 0)
(void)fprintf(stderr, "[try elf %d]\n",
m);
@@ -282,7 +281,7 @@ file_buffer(struct magic_set *ms, int fd, const char *inname __attribute__ ((__u
/* try text properties */
if ((ms->flags & MAGIC_NO_CHECK_TEXT) == 0) {
- m = file_ascmagic(ms, ubuf, nb, looks_text);
+ m = file_ascmagic(ms, &b, looks_text);
if ((ms->flags & MAGIC_DEBUG) != 0)
(void)fprintf(stderr, "[try ascmagic %d]\n", m);
if (m) {
@@ -319,7 +318,7 @@ simple:
#if HAVE_FORK
done_encoding:
#endif
- free(u8buf);
+ buffer_fini(&b);
if (rv)
return rv;
diff --git a/src/is_tar.c b/src/is_tar.c
index 1953a7fc102e..7110604f9e81 100644
--- a/src/is_tar.c
+++ b/src/is_tar.c
@@ -40,7 +40,7 @@
#include "file.h"
#ifndef lint
-FILE_RCSID("@(#)$File: is_tar.c,v 1.39 2017/03/17 20:45:01 christos Exp $")
+FILE_RCSID("@(#)$File: is_tar.c,v 1.41 2017/11/02 20:25:39 christos Exp $")
#endif
#include "magic.h"
@@ -53,15 +53,17 @@ FILE_RCSID("@(#)$File: is_tar.c,v 1.39 2017/03/17 20:45:01 christos Exp $")
private int is_tar(const unsigned char *, size_t);
private int from_oct(const char *, size_t); /* Decode octal number */
-static const char tartype[][32] = {
- "tar archive",
+static const char tartype[][32] = { /* should be equal to messages */
+ "tar archive", /* found in ../magic/Magdir/archive */
"POSIX tar archive",
- "POSIX tar archive (GNU)",
+ "POSIX tar archive (GNU)", /* */
};
protected int
-file_is_tar(struct magic_set *ms, const unsigned char *buf, size_t nbytes)
+file_is_tar(struct magic_set *ms, const struct buffer *b)
{
+ const unsigned char *buf = b->fbuf;
+ size_t nbytes = b->flen;
/*
* Do the tar test first, because if the first file in the tar
* archive starts with a dot, we can confuse it with an nroff file.
diff --git a/src/readcdf.c b/src/readcdf.c
index 80c8d26e3fec..51b862cf168a 100644
--- a/src/readcdf.c
+++ b/src/readcdf.c
@@ -26,7 +26,7 @@
#include "file.h"
#ifndef lint
-FILE_RCSID("@(#)$File: readcdf.c,v 1.65 2017/04/08 20:58:03 christos Exp $")
+FILE_RCSID("@(#)$File: readcdf.c,v 1.66 2017/11/02 20:25:39 christos Exp $")
#endif
#include <assert.h>
@@ -537,9 +537,11 @@ cdf_file_dir_info(struct magic_set *ms, const cdf_dir_t *dir)
}
protected int
-file_trycdf(struct magic_set *ms, int fd, const unsigned char *buf,
- size_t nbytes)
+file_trycdf(struct magic_set *ms, const struct buffer *b)
{
+ int fd = b->fd;
+ const unsigned char *buf = b->fbuf;
+ size_t nbytes = b->flen;
cdf_info_t info;
cdf_header_t h;
cdf_sat_t sat, ssat;
diff --git a/src/readelf.c b/src/readelf.c
index 5f425c974e76..3df0836d7029 100644
--- a/src/readelf.c
+++ b/src/readelf.c
@@ -27,7 +27,7 @@
#include "file.h"
#ifndef lint
-FILE_RCSID("@(#)$File: readelf.c,v 1.138 2017/08/27 07:55:02 christos Exp $")
+FILE_RCSID("@(#)$File: readelf.c,v 1.141 2018/04/12 16:50:52 christos Exp $")
#endif
#ifdef BUILTIN_ELF
@@ -310,18 +310,19 @@ private const char os_style_names[][8] = {
"NetBSD",
};
-#define FLAGS_CORE_STYLE 0x003
+#define FLAGS_CORE_STYLE 0x0003
-#define FLAGS_DID_CORE 0x004
-#define FLAGS_DID_OS_NOTE 0x008
-#define FLAGS_DID_BUILD_ID 0x010
-#define FLAGS_DID_CORE_STYLE 0x020
-#define FLAGS_DID_NETBSD_PAX 0x040
-#define FLAGS_DID_NETBSD_MARCH 0x080
-#define FLAGS_DID_NETBSD_CMODEL 0x100
-#define FLAGS_DID_NETBSD_UNKNOWN 0x200
-#define FLAGS_IS_CORE 0x400
-#define FLAGS_DID_AUXV 0x800
+#define FLAGS_DID_CORE 0x0004
+#define FLAGS_DID_OS_NOTE 0x0008
+#define FLAGS_DID_BUILD_ID 0x0010
+#define FLAGS_DID_CORE_STYLE 0x0020
+#define FLAGS_DID_NETBSD_PAX 0x0040
+#define FLAGS_DID_NETBSD_MARCH 0x0080
+#define FLAGS_DID_NETBSD_CMODEL 0x0100
+#define FLAGS_DID_NETBSD_EMULATION 0x0200
+#define FLAGS_DID_NETBSD_UNKNOWN 0x0400
+#define FLAGS_IS_CORE 0x0800
+#define FLAGS_DID_AUXV 0x1000
private int
dophn_core(struct magic_set *ms, int clazz, int swap, int fd, off_t off,
@@ -726,11 +727,11 @@ do_core_note(struct magic_set *ms, unsigned char *nbuf, uint32_t type,
"gid=%u, nlwps=%u, lwp=%u (signal %u/code %u)",
file_printable(sbuf, sizeof(sbuf),
CAST(char *, pi.cpi_name)),
- elf_getu32(swap, pi.cpi_pid),
+ elf_getu32(swap, (uint32_t)pi.cpi_pid),
elf_getu32(swap, pi.cpi_euid),
elf_getu32(swap, pi.cpi_egid),
elf_getu32(swap, pi.cpi_nlwps),
- elf_getu32(swap, pi.cpi_siglwp),
+ elf_getu32(swap, (uint32_t)pi.cpi_siglwp),
elf_getu32(swap, pi.cpi_signo),
elf_getu32(swap, pi.cpi_sigcode)) == -1)
return 1;
@@ -908,6 +909,7 @@ get_string_on_virtaddr(struct magic_set *ms,
}
+/*ARGSUSED*/
private int
do_auxv_note(struct magic_set *ms, unsigned char *nbuf, uint32_t type,
int swap, uint32_t namesz __attribute__((__unused__)),
@@ -1134,6 +1136,14 @@ donote(struct magic_set *ms, void *vbuf, size_t offset, size_t size,
(int)descsz, (const char *)&nbuf[doff]) == -1)
return offset;
break;
+ case NT_NETBSD_EMULATION:
+ if (*flags & FLAGS_DID_NETBSD_EMULATION)
+ return offset;
+ *flags |= FLAGS_DID_NETBSD_EMULATION;
+ if (file_printf(ms, ", emulation: %.*s",
+ (int)descsz, (const char *)&nbuf[doff]) == -1)
+ return offset;
+ break;
default:
if (*flags & FLAGS_DID_NETBSD_UNKNOWN)
return offset;
@@ -1570,9 +1580,11 @@ dophn_exec(struct magic_set *ms, int clazz, int swap, int fd, off_t off,
protected int
-file_tryelf(struct magic_set *ms, int fd, const unsigned char *buf,
- size_t nbytes)
+file_tryelf(struct magic_set *ms, const struct buffer *b)
{
+ int fd = b->fd;
+ const unsigned char *buf = b->fbuf;
+ size_t nbytes = b->flen;
union {
int32_t l;
char c[sizeof (int32_t)];
diff --git a/src/seccomp.c b/src/seccomp.c
new file mode 100644
index 000000000000..7c8a31443b43
--- /dev/null
+++ b/src/seccomp.c
@@ -0,0 +1,246 @@
+/*
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice immediately at the beginning of the file, without modification,
+ * this list of conditions, and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+/*
+ * libseccomp hooks.
+ */
+#include "file.h"
+
+#ifndef lint
+FILE_RCSID("@(#)$File: seccomp.c,v 1.2 2017/11/04 01:14:25 christos Exp $")
+#endif /* lint */
+
+#if HAVE_LIBSECCOMP
+#include <seccomp.h> /* libseccomp */
+#include <sys/prctl.h> /* prctl */
+#include <sys/socket.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <errno.h>
+
+#define DENY_RULE(call) \
+ do \
+ if (seccomp_rule_add (ctx, SCMP_ACT_KILL, SCMP_SYS(call), 0) == -1) \
+ goto out; \
+ while (/*CONSTCOND*/0)
+#define ALLOW_RULE(call) \
+ do \
+ if (seccomp_rule_add (ctx, SCMP_ACT_ALLOW, SCMP_SYS(call), 0) == -1) \
+ goto out; \
+ while (/*CONSTCOND*/0)
+
+static scmp_filter_ctx ctx;
+
+
+int
+enable_sandbox_basic(void)
+{
+
+ if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) == -1)
+ return -1;
+
+#if 0
+ // prevent escape via ptrace
+ prctl(PR_SET_DUMPABLE, 0);
+#endif
+
+ if (prctl (PR_SET_DUMPABLE, 0, 0, 0, 0) == -1)
+ return -1;
+
+ // initialize the filter
+ ctx = seccomp_init(SCMP_ACT_ALLOW);
+ if (ctx == NULL)
+ return 1;
+
+ DENY_RULE(_sysctl);
+ DENY_RULE(acct);
+ DENY_RULE(add_key);
+ DENY_RULE(adjtimex);
+ DENY_RULE(chroot);
+ DENY_RULE(clock_adjtime);
+ DENY_RULE(create_module);
+ DENY_RULE(delete_module);
+ DENY_RULE(fanotify_init);
+ DENY_RULE(finit_module);
+ DENY_RULE(get_kernel_syms);
+ DENY_RULE(get_mempolicy);
+ DENY_RULE(init_module);
+ DENY_RULE(io_cancel);
+ DENY_RULE(io_destroy);
+ DENY_RULE(io_getevents);
+ DENY_RULE(io_setup);
+ DENY_RULE(io_submit);
+ DENY_RULE(ioperm);
+ DENY_RULE(iopl);
+ DENY_RULE(ioprio_set);
+ DENY_RULE(kcmp);
+#ifdef __NR_kexec_file_load
+ DENY_RULE(kexec_file_load);
+#endif
+ DENY_RULE(kexec_load);
+ DENY_RULE(keyctl);
+ DENY_RULE(lookup_dcookie);
+ DENY_RULE(mbind);
+ DENY_RULE(nfsservctl);
+ DENY_RULE(migrate_pages);
+ DENY_RULE(modify_ldt);
+ DENY_RULE(mount);
+ DENY_RULE(move_pages);
+ DENY_RULE(name_to_handle_at);
+ DENY_RULE(open_by_handle_at);
+ DENY_RULE(perf_event_open);
+ DENY_RULE(pivot_root);
+ DENY_RULE(process_vm_readv);
+ DENY_RULE(process_vm_writev);
+ DENY_RULE(ptrace);
+ DENY_RULE(reboot);
+ DENY_RULE(remap_file_pages);
+ DENY_RULE(request_key);
+ DENY_RULE(set_mempolicy);
+ DENY_RULE(swapoff);
+ DENY_RULE(swapon);
+ DENY_RULE(sysfs);
+ DENY_RULE(syslog);
+ DENY_RULE(tuxcall);
+ DENY_RULE(umount2);
+ DENY_RULE(uselib);
+ DENY_RULE(vmsplice);
+
+ // blocking dangerous syscalls that file should not need
+ DENY_RULE (execve);
+ DENY_RULE (socket);
+ // ...
+
+
+ // applying filter...
+ if (seccomp_load (ctx) == -1)
+ goto out;
+ // free ctx after the filter has been loaded into the kernel
+ seccomp_release(ctx);
+ return 0;
+
+out:
+ seccomp_release(ctx);
+ return -1;
+}
+
+
+int
+enable_sandbox_full(void)
+{
+
+ // prevent child processes from getting more priv e.g. via setuid,
+ // capabilities, ...
+ if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) == -1)
+ return -1;
+
+ if (prctl(PR_SET_DUMPABLE, 0, 0, 0, 0) == -1)
+ return -1;
+
+ // initialize the filter
+ ctx = seccomp_init(SCMP_ACT_KILL);
+ if (ctx == NULL)
+ return -1;
+
+ ALLOW_RULE(access);
+ ALLOW_RULE(brk);
+ ALLOW_RULE(close);
+ ALLOW_RULE(dup2);
+ ALLOW_RULE(exit);
+ ALLOW_RULE(exit_group);
+ ALLOW_RULE(fcntl);
+ ALLOW_RULE(fstat);
+ ALLOW_RULE(getdents);
+ ALLOW_RULE(ioctl);
+ ALLOW_RULE(lseek);
+ ALLOW_RULE(lstat);
+ ALLOW_RULE(mmap);
+ ALLOW_RULE(mprotect);
+ ALLOW_RULE(mremap);
+ ALLOW_RULE(munmap);
+ ALLOW_RULE(open);
+ ALLOW_RULE(openat);
+ ALLOW_RULE(pread64);
+ ALLOW_RULE(read);
+ ALLOW_RULE(readlink);
+ ALLOW_RULE(rt_sigaction);
+ ALLOW_RULE(rt_sigprocmask);
+ ALLOW_RULE(rt_sigreturn);
+ ALLOW_RULE(select);
+ ALLOW_RULE(stat);
+ ALLOW_RULE(sysinfo);
+ ALLOW_RULE(unlink);
+ ALLOW_RULE(write);
+
+
+#if 0
+ // needed by valgrind
+ ALLOW_RULE(gettid);
+ ALLOW_RULE(getpid);
+ ALLOW_RULE(rt_sigtimedwait);
+#endif
+
+#if 0
+ /* special restrictions for socket, only allow AF_UNIX/AF_LOCAL */
+ if (seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(socket), 1,
+ SCMP_CMP(0, SCMP_CMP_EQ, AF_UNIX)) == -1)
+ goto out;
+
+ if (seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(socket), 1,
+ SCMP_CMP(0, SCMP_CMP_EQ, AF_LOCAL)) == -1)
+ goto out;
+
+
+ /* special restrictions for open, prevent opening files for writing */
+ if (seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(open), 1,
+ SCMP_CMP(1, SCMP_CMP_MASKED_EQ, O_WRONLY | O_RDWR, 0)) == -1)
+ goto out;
+
+ if (seccomp_rule_add(ctx, SCMP_ACT_ERRNO(EACCES), SCMP_SYS(open), 1,
+ SCMP_CMP(1, SCMP_CMP_MASKED_EQ, O_WRONLY, O_WRONLY)) == -1)
+ goto out;
+
+ if (seccomp_rule_add(ctx, SCMP_ACT_ERRNO(EACCES), SCMP_SYS(open), 1,
+ SCMP_CMP(1, SCMP_CMP_MASKED_EQ, O_RDWR, O_RDWR)) == -1)
+ goto out;
+
+
+ /* allow stderr */
+ if (seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(write), 1,
+ SCMP_CMP(0, SCMP_CMP_EQ, 2)) == -1)
+ goto out;
+#endif
+
+ // applying filter...
+ if (seccomp_load(ctx) == -1)
+ goto out;
+ // free ctx after the filter has been loaded into the kernel
+ seccomp_release(ctx);
+ return 0;
+
+out:
+ // something went wrong
+ seccomp_release(ctx);
+ return -1;
+}
+#endif
diff --git a/src/softmagic.c b/src/softmagic.c
index b9e975374b40..00d5aac6000f 100644
--- a/src/softmagic.c
+++ b/src/softmagic.c
@@ -32,7 +32,7 @@
#include "file.h"
#ifndef lint
-FILE_RCSID("@(#)$File: softmagic.c,v 1.249 2017/06/19 18:30:25 christos Exp $")
+FILE_RCSID("@(#)$File: softmagic.c,v 1.259 2018/03/11 01:23:52 christos Exp $")
#endif /* lint */
#include "magic.h"
@@ -44,20 +44,26 @@ FILE_RCSID("@(#)$File: softmagic.c,v 1.249 2017/06/19 18:30:25 christos Exp $")
#include "der.h"
private int match(struct magic_set *, struct magic *, uint32_t,
- const unsigned char *, size_t, size_t, int, int, int, uint16_t *,
+ const struct buffer *, size_t, int, int, int, uint16_t *,
uint16_t *, int *, int *, int *);
-private int mget(struct magic_set *, const unsigned char *,
- struct magic *, size_t, size_t, unsigned int, int, int, int, uint16_t *,
+private int mget(struct magic_set *, struct magic *, const struct buffer *,
+ const unsigned char *, size_t,
+ size_t, unsigned int, int, int, int, uint16_t *,
uint16_t *, int *, int *, int *);
+private int msetoffset(struct magic_set *, struct magic *, struct buffer *,
+ const struct buffer *, size_t, unsigned int);
private int magiccheck(struct magic_set *, struct magic *);
-private int32_t mprint(struct magic_set *, struct magic *);
-private int moffset(struct magic_set *, struct magic *, size_t, int32_t *);
+private int32_t mprint(struct magic_set *, struct magic *,
+ const struct buffer *);
+private int moffset(struct magic_set *, struct magic *, const struct buffer *,
+ int32_t *);
private void mdebug(uint32_t, const char *, size_t);
private int mcopy(struct magic_set *, union VALUETYPE *, int, int,
const unsigned char *, uint32_t, size_t, struct magic *);
private int mconvert(struct magic_set *, struct magic *, int);
private int print_sep(struct magic_set *, int);
-private int handle_annotation(struct magic_set *, struct magic *, int);
+private int handle_annotation(struct magic_set *, struct magic *,
+ const struct buffer *, int);
private int cvt_8(union VALUETYPE *, const struct magic *);
private int cvt_16(union VALUETYPE *, const struct magic *);
private int cvt_32(union VALUETYPE *, const struct magic *);
@@ -88,7 +94,7 @@ private int cvt_64(union VALUETYPE *, const struct magic *);
*/
/*ARGSUSED1*/ /* nbytes passed for regularity, maybe need later */
protected int
-file_softmagic(struct magic_set *ms, const unsigned char *buf, size_t nbytes,
+file_softmagic(struct magic_set *ms, const struct buffer *b,
uint16_t *indir_count, uint16_t *name_count, int mode, int text)
{
struct mlist *ml;
@@ -105,7 +111,7 @@ file_softmagic(struct magic_set *ms, const unsigned char *buf, size_t nbytes,
}
for (ml = ms->mlist[0]->next; ml != ms->mlist[0]; ml = ml->next)
- if ((rv = match(ms, ml->magic, ml->nmagic, buf, nbytes, 0, mode,
+ if ((rv = match(ms, ml->magic, ml->nmagic, b, 0, mode,
text, 0, indir_count, name_count,
&printed_something, &need_separator, NULL)) != 0)
return rv;
@@ -118,18 +124,18 @@ file_softmagic(struct magic_set *ms, const unsigned char *buf, size_t nbytes,
#define F(a, b, c) file_fmtcheck((a), (b), (c), __FILE__, __LINE__)
private const char * __attribute__((__format_arg__(3)))
-file_fmtcheck(struct magic_set *ms, const struct magic *m, const char *def,
+file_fmtcheck(struct magic_set *ms, const char *desc, const char *def,
const char *file, size_t line)
{
- const char *ptr = fmtcheck(m->desc, def);
+ const char *ptr = fmtcheck(desc, def);
if (ptr == def)
file_magerror(ms,
"%s, %" SIZE_T_FORMAT "u: format `%s' does not match"
- " with `%s'", file, line, m->desc, def);
+ " with `%s'", file, line, desc, def);
return ptr;
}
#else
-#define F(a, b, c) fmtcheck((b)->desc, (c))
+#define F(a, b, c) fmtcheck((b), (c))
#endif
/*
@@ -161,7 +167,7 @@ file_fmtcheck(struct magic_set *ms, const struct magic *m, const char *def,
*/
private int
match(struct magic_set *ms, struct magic *magic, uint32_t nmagic,
- const unsigned char *s, size_t nbytes, size_t offset, int mode, int text,
+ const struct buffer *b, size_t offset, int mode, int text,
int flip, uint16_t *indir_count, uint16_t *name_count,
int *printed_something, int *need_separator, int *returnval)
{
@@ -169,6 +175,7 @@ match(struct magic_set *ms, struct magic *magic, uint32_t nmagic,
unsigned int cont_level = 0;
int returnvalv = 0, e; /* if a match is found it is set to 1*/
int firstline = 1; /* a flag to print X\n X\n- X */
+ struct buffer bb;
int print = (ms->flags & MAGIC_NODESC) == 0;
if (returnval == NULL)
@@ -196,12 +203,13 @@ flush:
continue; /* Skip to next top-level test*/
}
- ms->offset = m->offset;
+ if (msetoffset(ms, m, &bb, b, offset, cont_level) == -1)
+ goto flush;
ms->line = m->lineno;
/* if main entry matches, print it... */
- switch (mget(ms, s, m, nbytes, offset, cont_level, mode, text,
- flip, indir_count, name_count,
+ switch (mget(ms, m, b, bb.fbuf, bb.flen, offset, cont_level,
+ mode, text, flip, indir_count, name_count,
printed_something, need_separator, returnval)) {
case -1:
return -1;
@@ -232,7 +240,7 @@ flush:
goto flush;
}
- if ((e = handle_annotation(ms, m, firstline)) != 0) {
+ if ((e = handle_annotation(ms, m, b, firstline)) != 0) {
*need_separator = 1;
*printed_something = 1;
*returnval = 1;
@@ -250,11 +258,10 @@ flush:
return -1;
}
-
- if (print && mprint(ms, m) == -1)
+ if (print && mprint(ms, m, b) == -1)
return -1;
- switch (moffset(ms, m, nbytes, &ms->c.li[cont_level].off)) {
+ switch (moffset(ms, m, &bb, &ms->c.li[cont_level].off)) {
case -1:
case 0:
goto flush;
@@ -280,7 +287,8 @@ flush:
*/
cont_level = m->cont_level;
}
- ms->offset = m->offset;
+ if (msetoffset(ms, m, &bb, b, offset, cont_level) == -1)
+ goto flush;
if (m->flag & OFFADD) {
ms->offset +=
ms->c.li[cont_level - 1].off;
@@ -293,9 +301,10 @@ flush:
continue;
}
#endif
- switch (mget(ms, s, m, nbytes, offset, cont_level, mode,
- text, flip, indir_count, name_count,
- printed_something, need_separator, returnval)) {
+ switch (mget(ms, m, b, bb.fbuf, bb.flen, offset,
+ cont_level, mode, text, flip, indir_count,
+ name_count, printed_something, need_separator,
+ returnval)) {
case -1:
return -1;
case 0:
@@ -330,7 +339,8 @@ flush:
} else
ms->c.li[cont_level].got_match = 1;
- if ((e = handle_annotation(ms, m, firstline)) != 0) {
+ if ((e = handle_annotation(ms, m, b, firstline))
+ != 0) {
*need_separator = 1;
*printed_something = 1;
*returnval = 1;
@@ -363,10 +373,10 @@ flush:
return -1;
*need_separator = 0;
}
- if (print && mprint(ms, m) == -1)
+ if (print && mprint(ms, m, b) == -1)
return -1;
- switch (moffset(ms, m, nbytes,
+ switch (moffset(ms, m, &bb,
&ms->c.li[cont_level].off)) {
case -1:
case 0:
@@ -404,19 +414,19 @@ flush:
}
private int
-check_fmt(struct magic_set *ms, struct magic *m)
+check_fmt(struct magic_set *ms, const char *fmt)
{
file_regex_t rx;
int rc, rv = -1;
- if (strchr(m->desc, '%') == NULL)
+ if (strchr(fmt, '%') == NULL)
return 0;
rc = file_regcomp(&rx, "%[-0-9\\.]*s", REG_EXTENDED|REG_NOSUB);
if (rc) {
file_regerror(&rx, rc, ms);
} else {
- rc = file_regexec(&rx, m->desc, 0, 0, 0);
+ rc = file_regexec(&rx, fmt, 0, 0, 0);
rv = !rc;
}
file_regfree(&rx);
@@ -442,30 +452,91 @@ strndup(const char *str, size_t n)
}
#endif /* HAVE_STRNDUP */
+static int
+varexpand(char *buf, size_t len, const struct buffer *b, const char *str)
+{
+ const char *ptr, *sptr, *e, *t, *ee, *et;
+ size_t l;
+
+ for (sptr = str; (ptr = strstr(sptr, "${")) != NULL;) {
+ l = (size_t)(ptr - sptr);
+ if (l >= len)
+ return -1;
+ memcpy(buf, sptr, l);
+ buf += l;
+ len -= l;
+ ptr += 2;
+ if (!*ptr || ptr[1] != '?')
+ return -1;
+ for (et = t = ptr + 2; *et && *et != ':'; et++)
+ continue;
+ if (*et != ':')
+ return -1;
+ for (ee = e = et + 1; *ee && *ee != '}'; ee++)
+ continue;
+ if (*ee != '}')
+ return -1;
+ switch (*ptr) {
+ case 'x':
+ if (b->st.st_mode & 0111) {
+ ptr = t;
+ l = et - t;
+ } else {
+ ptr = e;
+ l = ee - e;
+ }
+ break;
+ default:
+ return -1;
+ }
+ if (l >= len)
+ return -1;
+ memcpy(buf, ptr, l);
+ buf += l;
+ len -= l;
+ sptr = ee + 1;
+ }
+
+ l = strlen(sptr);
+ if (l >= len)
+ return -1;
+
+ memcpy(buf, sptr, l);
+ buf[l] = '\0';
+ return 0;
+}
+
+
private int32_t
-mprint(struct magic_set *ms, struct magic *m)
+mprint(struct magic_set *ms, struct magic *m, const struct buffer *b)
{
uint64_t v;
float vf;
double vd;
int64_t t = 0;
- char buf[128], tbuf[26], sbuf[512];
+ char buf[128], tbuf[26], sbuf[512], ebuf[512];
+ const char *desc;
union VALUETYPE *p = &ms->ms_value;
+ if (varexpand(ebuf, sizeof(ebuf), b, m->desc) == -1)
+ desc = m->desc;
+ else
+ desc = ebuf;
+
switch (m->type) {
case FILE_BYTE:
v = file_signextend(ms, m, (uint64_t)p->b);
- switch (check_fmt(ms, m)) {
+ switch (check_fmt(ms, desc)) {
case -1:
return -1;
case 1:
(void)snprintf(buf, sizeof(buf), "%d",
(unsigned char)v);
- if (file_printf(ms, F(ms, m, "%s"), buf) == -1)
+ if (file_printf(ms, F(ms, desc, "%s"), buf) == -1)
return -1;
break;
default:
- if (file_printf(ms, F(ms, m, "%d"),
+ if (file_printf(ms, F(ms, desc, "%d"),
(unsigned char) v) == -1)
return -1;
break;
@@ -477,17 +548,17 @@ mprint(struct magic_set *ms, struct magic *m)
case FILE_BESHORT:
case FILE_LESHORT:
v = file_signextend(ms, m, (uint64_t)p->h);
- switch (check_fmt(ms, m)) {
+ switch (check_fmt(ms, desc)) {
case -1:
return -1;
case 1:
(void)snprintf(buf, sizeof(buf), "%u",
(unsigned short)v);
- if (file_printf(ms, F(ms, m, "%s"), buf) == -1)
+ if (file_printf(ms, F(ms, desc, "%s"), buf) == -1)
return -1;
break;
default:
- if (file_printf(ms, F(ms, m, "%u"),
+ if (file_printf(ms, F(ms, desc, "%u"),
(unsigned short) v) == -1)
return -1;
break;
@@ -500,16 +571,16 @@ mprint(struct magic_set *ms, struct magic *m)
case FILE_LELONG:
case FILE_MELONG:
v = file_signextend(ms, m, (uint64_t)p->l);
- switch (check_fmt(ms, m)) {
+ switch (check_fmt(ms, desc)) {
case -1:
return -1;
case 1:
(void)snprintf(buf, sizeof(buf), "%u", (uint32_t) v);
- if (file_printf(ms, F(ms, m, "%s"), buf) == -1)
+ if (file_printf(ms, F(ms, desc, "%s"), buf) == -1)
return -1;
break;
default:
- if (file_printf(ms, F(ms, m, "%u"), (uint32_t) v) == -1)
+ if (file_printf(ms, F(ms, desc, "%u"), (uint32_t) v) == -1)
return -1;
break;
}
@@ -520,17 +591,17 @@ mprint(struct magic_set *ms, struct magic *m)
case FILE_BEQUAD:
case FILE_LEQUAD:
v = file_signextend(ms, m, p->q);
- switch (check_fmt(ms, m)) {
+ switch (check_fmt(ms, desc)) {
case -1:
return -1;
case 1:
(void)snprintf(buf, sizeof(buf), "%" INT64_T_FORMAT "u",
(unsigned long long)v);
- if (file_printf(ms, F(ms, m, "%s"), buf) == -1)
+ if (file_printf(ms, F(ms, desc, "%s"), buf) == -1)
return -1;
break;
default:
- if (file_printf(ms, F(ms, m, "%" INT64_T_FORMAT "u"),
+ if (file_printf(ms, F(ms, desc, "%" INT64_T_FORMAT "u"),
(unsigned long long) v) == -1)
return -1;
break;
@@ -543,7 +614,7 @@ mprint(struct magic_set *ms, struct magic *m)
case FILE_BESTRING16:
case FILE_LESTRING16:
if (m->reln == '=' || m->reln == '!') {
- if (file_printf(ms, F(ms, m, "%s"),
+ if (file_printf(ms, F(ms, desc, "%s"),
file_printable(sbuf, sizeof(sbuf), m->value.s))
== -1)
return -1;
@@ -571,7 +642,7 @@ mprint(struct magic_set *ms, struct magic *m)
*++last = '\0';
}
- if (file_printf(ms, F(ms, m, "%s"),
+ if (file_printf(ms, F(ms, desc, "%s"),
file_printable(sbuf, sizeof(sbuf), str)) == -1)
return -1;
@@ -584,7 +655,7 @@ mprint(struct magic_set *ms, struct magic *m)
case FILE_BEDATE:
case FILE_LEDATE:
case FILE_MEDATE:
- if (file_printf(ms, F(ms, m, "%s"),
+ if (file_printf(ms, F(ms, desc, "%s"),
file_fmttime(p->l, 0, tbuf)) == -1)
return -1;
t = ms->offset + sizeof(uint32_t);
@@ -594,7 +665,7 @@ mprint(struct magic_set *ms, struct magic *m)
case FILE_BELDATE:
case FILE_LELDATE:
case FILE_MELDATE:
- if (file_printf(ms, F(ms, m, "%s"),
+ if (file_printf(ms, F(ms, desc, "%s"),
file_fmttime(p->l, FILE_T_LOCAL, tbuf)) == -1)
return -1;
t = ms->offset + sizeof(uint32_t);
@@ -603,7 +674,7 @@ mprint(struct magic_set *ms, struct magic *m)
case FILE_QDATE:
case FILE_BEQDATE:
case FILE_LEQDATE:
- if (file_printf(ms, F(ms, m, "%s"),
+ if (file_printf(ms, F(ms, desc, "%s"),
file_fmttime(p->q, 0, tbuf)) == -1)
return -1;
t = ms->offset + sizeof(uint64_t);
@@ -612,7 +683,7 @@ mprint(struct magic_set *ms, struct magic *m)
case FILE_QLDATE:
case FILE_BEQLDATE:
case FILE_LEQLDATE:
- if (file_printf(ms, F(ms, m, "%s"),
+ if (file_printf(ms, F(ms, desc, "%s"),
file_fmttime(p->q, FILE_T_LOCAL, tbuf)) == -1)
return -1;
t = ms->offset + sizeof(uint64_t);
@@ -621,7 +692,7 @@ mprint(struct magic_set *ms, struct magic *m)
case FILE_QWDATE:
case FILE_BEQWDATE:
case FILE_LEQWDATE:
- if (file_printf(ms, F(ms, m, "%s"),
+ if (file_printf(ms, F(ms, desc, "%s"),
file_fmttime(p->q, FILE_T_WINDOWS, tbuf)) == -1)
return -1;
t = ms->offset + sizeof(uint64_t);
@@ -631,16 +702,16 @@ mprint(struct magic_set *ms, struct magic *m)
case FILE_BEFLOAT:
case FILE_LEFLOAT:
vf = p->f;
- switch (check_fmt(ms, m)) {
+ switch (check_fmt(ms, desc)) {
case -1:
return -1;
case 1:
(void)snprintf(buf, sizeof(buf), "%g", vf);
- if (file_printf(ms, F(ms, m, "%s"), buf) == -1)
+ if (file_printf(ms, F(ms, desc, "%s"), buf) == -1)
return -1;
break;
default:
- if (file_printf(ms, F(ms, m, "%g"), vf) == -1)
+ if (file_printf(ms, F(ms, desc, "%g"), vf) == -1)
return -1;
break;
}
@@ -651,16 +722,16 @@ mprint(struct magic_set *ms, struct magic *m)
case FILE_BEDOUBLE:
case FILE_LEDOUBLE:
vd = p->d;
- switch (check_fmt(ms, m)) {
+ switch (check_fmt(ms, desc)) {
case -1:
return -1;
case 1:
(void)snprintf(buf, sizeof(buf), "%g", vd);
- if (file_printf(ms, F(ms, m, "%s"), buf) == -1)
+ if (file_printf(ms, F(ms, desc, "%s"), buf) == -1)
return -1;
break;
default:
- if (file_printf(ms, F(ms, m, "%g"), vd) == -1)
+ if (file_printf(ms, F(ms, desc, "%g"), vd) == -1)
return -1;
break;
}
@@ -677,7 +748,7 @@ mprint(struct magic_set *ms, struct magic *m)
file_oomem(ms, ms->search.rm_len);
return -1;
}
- rval = file_printf(ms, F(ms, m, "%s"),
+ rval = file_printf(ms, F(ms, desc, "%s"),
file_printable(sbuf, sizeof(sbuf), cp));
free(cp);
@@ -704,7 +775,7 @@ mprint(struct magic_set *ms, struct magic *m)
t = ms->offset;
break;
case FILE_DER:
- if (file_printf(ms, F(ms, m, "%s"),
+ if (file_printf(ms, F(ms, desc, "%s"),
file_printable(sbuf, sizeof(sbuf), ms->ms_value.s)) == -1)
return -1;
t = ms->offset;
@@ -717,8 +788,10 @@ mprint(struct magic_set *ms, struct magic *m)
}
private int
-moffset(struct magic_set *ms, struct magic *m, size_t nbytes, int32_t *op)
+moffset(struct magic_set *ms, struct magic *m, const struct buffer *b,
+ int32_t *op)
{
+ size_t nbytes = b->flen;
int32_t o;
switch (m->type) {
@@ -1232,7 +1305,7 @@ mcopy(struct magic_set *ms, union VALUETYPE *p, int type, int indir,
b++;
}
if (lines)
- last = RCAST(const char *, s) + bytecnt;
+ last = end;
ms->search.s = buf;
ms->search.s_len = last - buf;
@@ -1337,12 +1410,58 @@ do_ops(struct magic *m, intmax_t lhs, intmax_t off)
}
private int
-mget(struct magic_set *ms, const unsigned char *s, struct magic *m,
- size_t nbytes, size_t o, unsigned int cont_level, int mode, int text,
- int flip, uint16_t *indir_count, uint16_t *name_count,
+msetoffset(struct magic_set *ms, struct magic *m, struct buffer *bb,
+ const struct buffer *b, size_t o, unsigned int cont_level)
+{
+ if (m->offset < 0) {
+ if (cont_level > 0) {
+ if (m->flag & (OFFADD|INDIROFFADD))
+ goto normal;
+#if 0
+ file_error(ms, 0, "negative offset %d at continuation"
+ "level %u", m->offset, cont_level);
+ return -1;
+#endif
+ }
+ if (buffer_fill(b) == -1)
+ return -1;
+ if (o != 0) {
+ // Not yet!
+ file_magerror(ms, "non zero offset %zu at"
+ " level %u", o, cont_level);
+ return -1;
+ }
+ if ((size_t)-m->offset > b->elen)
+ return -1;
+ buffer_init(bb, -1, b->ebuf, b->elen);
+ ms->eoffset = ms->offset = b->elen + m->offset;
+ } else {
+ if (cont_level == 0) {
+normal:
+ // XXX: Pass real fd, then who frees bb?
+ buffer_init(bb, -1, b->fbuf, b->flen);
+ ms->offset = m->offset;
+ ms->eoffset = 0;
+ } else {
+ ms->offset = ms->eoffset + m->offset;
+ }
+ }
+ if ((ms->flags & MAGIC_DEBUG) != 0) {
+ fprintf(stderr, "bb=[%p,%zu], %d [b=%p,%zu], [o=%#x, c=%d]\n",
+ bb->fbuf, bb->flen, ms->offset, b->fbuf, b->flen,
+ m->offset, cont_level);
+ }
+ return 0;
+}
+
+private int
+mget(struct magic_set *ms, struct magic *m, const struct buffer *b,
+ const unsigned char *s, size_t nbytes, size_t o, unsigned int cont_level,
+ int mode, int text, int flip, uint16_t *indir_count, uint16_t *name_count,
int *printed_something, int *need_separator, int *returnval)
{
uint32_t offset = ms->offset;
+ struct buffer bb;
intmax_t lhs;
file_pushbuf_t *pb;
int rv, oneed_separator, in_type;
@@ -1362,6 +1481,8 @@ mget(struct magic_set *ms, const unsigned char *s, struct magic *m,
return -1;
}
+
+
if (mcopy(ms, p, m->type, m->flag & INDIR, s, (uint32_t)(offset + o),
(uint32_t)nbytes, m) == -1)
return -1;
@@ -1559,7 +1680,10 @@ mget(struct magic_set *ms, const unsigned char *s, struct magic *m,
return -1;
(*indir_count)++;
- rv = file_softmagic(ms, s + offset, nbytes - offset,
+ bb = *b;
+ bb.fbuf = s + offset;
+ bb.flen = nbytes - offset;
+ rv = file_softmagic(ms, &bb,
indir_count, name_count, BINTEST, text);
if ((ms->flags & MAGIC_DEBUG) != 0)
@@ -1571,7 +1695,7 @@ mget(struct magic_set *ms, const unsigned char *s, struct magic *m,
if (rv == 1) {
if ((ms->flags & MAGIC_NODESC) == 0 &&
- file_printf(ms, F(ms, m, "%u"), offset) == -1) {
+ file_printf(ms, F(ms, m->desc, "%u"), offset) == -1) {
free(rbuf);
return -1;
}
@@ -1599,12 +1723,12 @@ mget(struct magic_set *ms, const unsigned char *s, struct magic *m,
oneed_separator = *need_separator;
if (m->flag & NOSPACE)
*need_separator = 0;
- rv = match(ms, ml.magic, ml.nmagic, s, nbytes, offset + o,
+ rv = match(ms, ml.magic, ml.nmagic, b, offset + o,
mode, text, flip, indir_count, name_count,
printed_something, need_separator, returnval);
if (rv != 1)
*need_separator = oneed_separator;
- return 1;
+ return rv;
case FILE_NAME:
if (ms->flags & MAGIC_NODESC)
@@ -2035,7 +2159,8 @@ magiccheck(struct magic_set *ms, struct magic *m)
}
private int
-handle_annotation(struct magic_set *ms, struct magic *m, int firstline)
+handle_annotation(struct magic_set *ms, struct magic *m, const struct buffer *b,
+ int firstline)
{
if ((ms->flags & MAGIC_APPLE) && m->apple[0]) {
if (!firstline && file_printf(ms, "\n- ") == -1)
@@ -2052,9 +2177,15 @@ handle_annotation(struct magic_set *ms, struct magic *m, int firstline)
return 1;
}
if ((ms->flags & MAGIC_MIME_TYPE) && m->mimetype[0]) {
+ char buf[1024];
+ const char *p;
if (!firstline && file_printf(ms, "\n- ") == -1)
return -1;
- if (file_printf(ms, "%s", m->mimetype) == -1)
+ if (varexpand(buf, sizeof(buf), b, m->mimetype) == -1)
+ p = m->mimetype;
+ else
+ p = buf;
+ if (file_printf(ms, "%s", p) == -1)
return -1;
return 1;
}