From 805288c2f062e70e8a9147e980840dcb119a7aa9 Mon Sep 17 00:00:00 2001 From: Xin LI Date: Wed, 10 Dec 2014 08:18:22 +0000 Subject: [PATCH 01/13] In r268924 __fflush was modified so that when write(2) was not successful, _p and _w are adjusted to account for the partial write (if any). However, _p and _w should not be unconditionally adjusted and should only be changed when we actually wrote some bytes, or the accumulated accounting error will eventually result in a heap buffer overflow. Reported by: adrian and alfred (Norse Corporation) Security: FreeBSD-SA-14:27.stdio Security: CVE-2014-8611 --- lib/libc/stdio/fflush.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/lib/libc/stdio/fflush.c b/lib/libc/stdio/fflush.c index ef9b45b8b6f1..123167a09129 100644 --- a/lib/libc/stdio/fflush.c +++ b/lib/libc/stdio/fflush.c @@ -124,11 +124,13 @@ __sflush(FILE *fp) t = _swrite(fp, (char *)p, n); if (t <= 0) { /* Reset _p and _w. */ - if (p > fp->_p) /* Some was written. */ + if (p > fp->_p) { + /* Some was written. */ memmove(fp->_p, p, n); - fp->_p += n; - if ((fp->_flags & (__SLBF | __SNBF)) == 0) - fp->_w -= n; + fp->_p += n; + if ((fp->_flags & (__SLBF | __SNBF)) == 0) + fp->_w -= n; + } fp->_flags |= __SERR; return (EOF); } From 2c4f16476d2b44a072e8bfbb158c44879f59d463 Mon Sep 17 00:00:00 2001 From: Xin LI Date: Wed, 10 Dec 2014 08:19:55 +0000 Subject: [PATCH 02/13] Fix multiple vulnerabilities in file(1) and libmagic(3). Security: FreeBSD-SA-14:28.file Security: CVE-2014-3710, CVE-2014-8116, CVE-2014-8117 --- contrib/file/src/elfclass.h | 24 ++++++++++++++-------- contrib/file/src/file.h | 8 ++++++++ contrib/file/src/funcs.c | 40 ++++++++++++++++++++++++++++++++++++ contrib/file/src/readelf.c | 30 ++++++++++++++++++++++++--- contrib/file/src/softmagic.c | 38 ++++++++++++++++++++-------------- 5 files changed, 114 insertions(+), 26 deletions(-) diff --git a/contrib/file/src/elfclass.h b/contrib/file/src/elfclass.h index 010958a4296f..0826ce3213a5 100644 --- a/contrib/file/src/elfclass.h +++ b/contrib/file/src/elfclass.h @@ -35,10 +35,12 @@ switch (type) { #ifdef ELFCORE case ET_CORE: + phnum = elf_getu16(swap, elfhdr.e_phnum); + if (phnum > MAX_PHNUM) + return toomany(ms, "program", phnum); flags |= FLAGS_IS_CORE; if (dophn_core(ms, clazz, swap, fd, - (off_t)elf_getu(swap, elfhdr.e_phoff), - elf_getu16(swap, elfhdr.e_phnum), + (off_t)elf_getu(swap, elfhdr.e_phoff), phnum, (size_t)elf_getu16(swap, elfhdr.e_phentsize), fsize, &flags) == -1) return -1; @@ -46,18 +48,24 @@ #endif case ET_EXEC: case ET_DYN: + phnum = elf_getu16(swap, elfhdr.e_phnum); + if (phnum > MAX_PHNUM) + return toomany(ms, "program", phnum); + shnum = elf_getu16(swap, elfhdr.e_shnum); + if (shnum > MAX_SHNUM) + return toomany(ms, "section", shnum); if (dophn_exec(ms, clazz, swap, fd, - (off_t)elf_getu(swap, elfhdr.e_phoff), - elf_getu16(swap, elfhdr.e_phnum), + (off_t)elf_getu(swap, elfhdr.e_phoff), phnum, (size_t)elf_getu16(swap, elfhdr.e_phentsize), - fsize, &flags, elf_getu16(swap, elfhdr.e_shnum)) - == -1) + fsize, &flags, shnum) == -1) return -1; /*FALLTHROUGH*/ case ET_REL: + shnum = elf_getu16(swap, elfhdr.e_shnum); + if (shnum > MAX_SHNUM) + return toomany(ms, "section", shnum); if (doshn(ms, clazz, swap, fd, - (off_t)elf_getu(swap, elfhdr.e_shoff), - elf_getu16(swap, elfhdr.e_shnum), + (off_t)elf_getu(swap, elfhdr.e_shoff), shnum, (size_t)elf_getu16(swap, elfhdr.e_shentsize), fsize, &flags, elf_getu16(swap, elfhdr.e_machine), (int)elf_getu16(swap, elfhdr.e_shstrndx)) == -1) diff --git a/contrib/file/src/file.h b/contrib/file/src/file.h index 67a25680cd2d..1a652a87d50f 100644 --- a/contrib/file/src/file.h +++ b/contrib/file/src/file.h @@ -482,6 +482,14 @@ protected int file_regexec(file_regex_t *, const char *, size_t, regmatch_t *, protected void file_regfree(file_regex_t *); protected void file_regerror(file_regex_t *, int, struct magic_set *); +typedef struct { + char *buf; + uint32_t offset; +} file_pushbuf_t; + +protected file_pushbuf_t *file_push_buffer(struct magic_set *); +protected char *file_pop_buffer(struct magic_set *, file_pushbuf_t *); + #ifndef COMPILE_ONLY extern const char *file_names[]; extern const size_t file_nnames; diff --git a/contrib/file/src/funcs.c b/contrib/file/src/funcs.c index 3a2f67c4dab8..7e7d2e77cb0c 100644 --- a/contrib/file/src/funcs.c +++ b/contrib/file/src/funcs.c @@ -491,3 +491,43 @@ file_regerror(file_regex_t *rx, int rc, struct magic_set *ms) file_magerror(ms, "regex error %d for `%s', (%s)", rc, rx->pat, errmsg); } + +protected file_pushbuf_t * +file_push_buffer(struct magic_set *ms) +{ + file_pushbuf_t *pb; + + if (ms->event_flags & EVENT_HAD_ERR) + return NULL; + + if ((pb = (CAST(file_pushbuf_t *, malloc(sizeof(*pb))))) == NULL) + return NULL; + + pb->buf = ms->o.buf; + pb->offset = ms->offset; + + ms->o.buf = NULL; + ms->offset = 0; + + return pb; +} + +protected char * +file_pop_buffer(struct magic_set *ms, file_pushbuf_t *pb) +{ + char *rbuf; + + if (ms->event_flags & EVENT_HAD_ERR) { + free(pb->buf); + free(pb); + return NULL; + } + + rbuf = ms->o.buf; + + ms->o.buf = pb->buf; + ms->offset = pb->offset; + + free(pb); + return rbuf; +} diff --git a/contrib/file/src/readelf.c b/contrib/file/src/readelf.c index ede7e0c751c8..55b7e980b918 100644 --- a/contrib/file/src/readelf.c +++ b/contrib/file/src/readelf.c @@ -60,6 +60,18 @@ private uint16_t getu16(int, uint16_t); private uint32_t getu32(int, uint32_t); private uint64_t getu64(int, uint64_t); +#define MAX_PHNUM 256 +#define MAX_SHNUM 1024 + +private int +toomany(struct magic_set *ms, const char *name, uint16_t num) +{ + if (file_printf(ms, ", too many %s header sections (%u)", name, num + ) == -1) + return -1; + return 0; +} + private uint16_t getu16(int swap, uint16_t value) { @@ -477,6 +489,13 @@ donote(struct magic_set *ms, void *vbuf, size_t offset, size_t size, uint32_t namesz, descsz; unsigned char *nbuf = CAST(unsigned char *, vbuf); + if (xnh_sizeof + offset > size) { + /* + * We're out of note headers. + */ + return xnh_sizeof + offset; + } + (void)memcpy(xnh_addr, &nbuf[offset], xnh_sizeof); offset += xnh_sizeof; @@ -492,13 +511,13 @@ donote(struct magic_set *ms, void *vbuf, size_t offset, size_t size, if (namesz & 0x80000000) { (void)file_printf(ms, ", bad note name size 0x%lx", (unsigned long)namesz); - return offset; + return 0; } if (descsz & 0x80000000) { (void)file_printf(ms, ", bad note description size 0x%lx", (unsigned long)descsz); - return offset; + return 0; } @@ -900,6 +919,7 @@ doshn(struct magic_set *ms, int clazz, int swap, int fd, off_t off, int num, Elf32_Shdr sh32; Elf64_Shdr sh64; int stripped = 1; + size_t nbadcap = 0; void *nbuf; off_t noff, coff, name_off; uint64_t cap_hw1 = 0; /* SunOS 5.x hardware capabilites */ @@ -988,6 +1008,8 @@ doshn(struct magic_set *ms, int clazz, int swap, int fd, off_t off, int num, goto skip; } + if (nbadcap > 5) + break; if (lseek(fd, xsh_offset, SEEK_SET) == (off_t)-1) { file_badseek(ms); return -1; @@ -1053,6 +1075,8 @@ doshn(struct magic_set *ms, int clazz, int swap, int fd, off_t off, int num, (unsigned long long)xcap_tag, (unsigned long long)xcap_val) == -1) return -1; + if (nbadcap++ > 2) + coff = xsh_size; break; } } @@ -1233,7 +1257,7 @@ file_tryelf(struct magic_set *ms, int fd, const unsigned char *buf, int flags = 0; Elf32_Ehdr elf32hdr; Elf64_Ehdr elf64hdr; - uint16_t type; + uint16_t type, phnum, shnum; if (ms->flags & (MAGIC_MIME|MAGIC_APPLE)) return 0; diff --git a/contrib/file/src/softmagic.c b/contrib/file/src/softmagic.c index ed97aa79d651..b0f193d6b2ae 100644 --- a/contrib/file/src/softmagic.c +++ b/contrib/file/src/softmagic.c @@ -67,6 +67,9 @@ private void cvt_32(union VALUETYPE *, const struct magic *); private void cvt_64(union VALUETYPE *, const struct magic *); #define OFFSET_OOB(n, o, i) ((n) < (o) || (i) > ((n) - (o))) + +#define MAX_RECURSION_LEVEL 10 + /* * softmagic - lookup one file in parsed, in-memory copy of database * Passed the name and FILE * of one file to be typed. @@ -1193,14 +1196,15 @@ mget(struct magic_set *ms, const unsigned char *s, struct magic *m, int flip, int recursion_level, int *printed_something, int *need_separator, int *returnval) { - uint32_t soffset, offset = ms->offset; + uint32_t offset = ms->offset; uint32_t lhs; + file_pushbuf_t *pb; int rv, oneed_separator, in_type; - char *sbuf, *rbuf; + char *rbuf; union VALUETYPE *p = &ms->ms_value; struct mlist ml; - if (recursion_level >= 20) { + if (recursion_level >= MAX_RECURSION_LEVEL) { file_error(ms, 0, "recursion nesting exceeded"); return -1; } @@ -1644,19 +1648,23 @@ mget(struct magic_set *ms, const unsigned char *s, struct magic *m, case FILE_INDIRECT: if (offset == 0) return 0; + if (nbytes < offset) return 0; - sbuf = ms->o.buf; - soffset = ms->offset; - ms->o.buf = NULL; - ms->offset = 0; + + if ((pb = file_push_buffer(ms)) == NULL) + return -1; + rv = file_softmagic(ms, s + offset, nbytes - offset, recursion_level, BINTEST, text); + if ((ms->flags & MAGIC_DEBUG) != 0) fprintf(stderr, "indirect @offs=%u[%d]\n", offset, rv); - rbuf = ms->o.buf; - ms->o.buf = sbuf; - ms->offset = soffset; + + rbuf = file_pop_buffer(ms, pb); + if (rbuf == NULL && ms->event_flags & EVENT_HAD_ERR) + return -1; + if (rv == 1) { if ((ms->flags & (MAGIC_MIME|MAGIC_APPLE)) == 0 && file_printf(ms, F(ms, m, "%u"), offset) == -1) { @@ -1674,13 +1682,13 @@ mget(struct magic_set *ms, const unsigned char *s, struct magic *m, case FILE_USE: if (nbytes < offset) return 0; - sbuf = m->value.s; - if (*sbuf == '^') { - sbuf++; + rbuf = m->value.s; + if (*rbuf == '^') { + rbuf++; flip = !flip; } - if (file_magicfind(ms, sbuf, &ml) == -1) { - file_error(ms, 0, "cannot find entry `%s'", sbuf); + if (file_magicfind(ms, rbuf, &ml) == -1) { + file_error(ms, 0, "cannot find entry `%s'", rbuf); return -1; } From 0767e98a2dc3b3309eebb051139c8b6c35991f8a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Roger=20Pau=20Monn=C3=A9?= Date: Wed, 10 Dec 2014 11:21:52 +0000 Subject: [PATCH 03/13] xen: move grant table code Mave the grant table code into the dev/xen folder in preparation for turning it into a device using the newbus interface. This is just code motion, no functional changes. Sponsored by: Citrix Systems R&D --- sys/conf/files | 2 +- sys/{xen/gnttab.c => dev/xen/grant_table/grant_table.c} | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename sys/{xen/gnttab.c => dev/xen/grant_table/grant_table.c} (100%) diff --git a/sys/conf/files b/sys/conf/files index f83785884242..1eea5e9572d5 100644 --- a/sys/conf/files +++ b/sys/conf/files @@ -2651,6 +2651,7 @@ dev/xen/blkback/blkback.c optional xen | xenhvm dev/xen/console/console.c optional xen | xenhvm dev/xen/console/xencons_ring.c optional xen | xenhvm dev/xen/control/control.c optional xen | xenhvm +dev/xen/grant_table/grant_table.c optional xen | xenhvm dev/xen/netback/netback.c optional xen | xenhvm dev/xen/netfront/netfront.c optional xen | xenhvm dev/xen/xenpci/xenpci.c optional xenpci @@ -4000,7 +4001,6 @@ vm/vm_reserv.c standard vm/vm_unix.c standard vm/vm_zeroidle.c standard vm/vnode_pager.c standard -xen/gnttab.c optional xen | xenhvm xen/features.c optional xen | xenhvm xen/xenbus/xenbus_if.m optional xen | xenhvm xen/xenbus/xenbus.c optional xen | xenhvm diff --git a/sys/xen/gnttab.c b/sys/dev/xen/grant_table/grant_table.c similarity index 100% rename from sys/xen/gnttab.c rename to sys/dev/xen/grant_table/grant_table.c From 74953fa3ca9bac0d34703352f7b4321988d55364 Mon Sep 17 00:00:00 2001 From: Ruslan Bukin Date: Wed, 10 Dec 2014 11:35:10 +0000 Subject: [PATCH 04/13] o Put () for p to avoid unexpected macro expansion o style(9) fix Submitted by: Yonghyeon PYUN --- sys/dev/mii/micphy.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/sys/dev/mii/micphy.c b/sys/dev/mii/micphy.c index 54e7c0f13e92..73c29f600ac7 100644 --- a/sys/dev/mii/micphy.c +++ b/sys/dev/mii/micphy.c @@ -68,7 +68,7 @@ __FBSDID("$FreeBSD$"); #define MII_KSZPHY_RX_DATA_PAD_SKEW 0x105 #define MII_KSZPHY_TX_DATA_PAD_SKEW 0x106 -#define PS_TO_REG(p) (p / 200) +#define PS_TO_REG(p) ((p) / 200) static int micphy_probe(device_t); static int micphy_attach(device_t); @@ -104,7 +104,8 @@ static const struct mii_phy_funcs micphy_funcs = { mii_phy_reset }; -static void micphy_write(struct mii_softc *sc, uint32_t reg, uint32_t val) +static void +micphy_write(struct mii_softc *sc, uint32_t reg, uint32_t val) { PHY_WRITE(sc, MII_KSZPHY_EXTREG, KSZPHY_EXTREG_WRITE | reg); From 1093cd82e0daf4ab31ba49e4f5067a2a158a1b41 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Roger=20Pau=20Monn=C3=A9?= Date: Wed, 10 Dec 2014 11:35:41 +0000 Subject: [PATCH 05/13] xen: convert the Grant-table code to a NewBus device This allows the Grant-table code to attach directly to the xenpv bus, allowing us to remove the grant-table initialization done in xenpv. Sponsored by: Citrix Systems R&D --- sys/dev/xen/grant_table/grant_table.c | 70 ++++++++++++++++++++++++--- sys/x86/xen/xenpv.c | 9 ---- sys/xen/gnttab.h | 2 - 3 files changed, 63 insertions(+), 18 deletions(-) diff --git a/sys/dev/xen/grant_table/grant_table.c b/sys/dev/xen/grant_table/grant_table.c index 9ab3145b4fee..25116575c023 100644 --- a/sys/dev/xen/grant_table/grant_table.c +++ b/sys/dev/xen/grant_table/grant_table.c @@ -659,16 +659,59 @@ gnttab_expand(unsigned int req_entries) return (error); } -int -gnttab_init(device_t dev) +MTX_SYSINIT(gnttab, &gnttab_list_lock, "GNTTAB LOCK", MTX_DEF); + +/*------------------ Private Device Attachment Functions --------------------*/ +/** + * \brief Identify instances of this device type in the system. + * + * \param driver The driver performing this identify action. + * \param parent The NewBus parent device for any devices this method adds. + */ +static void +granttable_identify(driver_t *driver __unused, device_t parent) +{ + + KASSERT(xen_domain(), + ("Trying to attach grant-table device on non Xen domain")); + /* + * A single device instance for our driver is always present + * in a system operating under Xen. + */ + if (BUS_ADD_CHILD(parent, 0, driver->name, 0) == NULL) + panic("unable to attach Xen Grant-table device"); +} + +/** + * \brief Probe for the existence of the Xen Grant-table device + * + * \param dev NewBus device_t for this instance. + * + * \return Always returns 0 indicating success. + */ +static int +granttable_probe(device_t dev) +{ + + device_set_desc(dev, "Xen Grant-table Device"); + return (BUS_PROBE_NOWILDCARD); +} + +/** + * \brief Attach the Xen Grant-table device. + * + * \param dev NewBus device_t for this instance. + * + * \return On success, 0. Otherwise an errno value indicating the + * type of failure. + */ +static int +granttable_attach(device_t dev) { int i; unsigned int max_nr_glist_frames; unsigned int nr_init_grefs; - if (!is_running_on_xen()) - return (ENODEV); - nr_grant_frames = 1; boot_max_nr_grant_frames = __max_nr_grant_frames(); @@ -714,7 +757,20 @@ gnttab_init(device_t dev) free(gnttab_list[i], M_DEVBUF); free(gnttab_list, M_DEVBUF); return (ENOMEM); - } -MTX_SYSINIT(gnttab, &gnttab_list_lock, "GNTTAB LOCK", MTX_DEF); +/*-------------------- Private Device Attachment Data -----------------------*/ +static device_method_t granttable_methods[] = { + /* Device interface */ + DEVMETHOD(device_identify, granttable_identify), + DEVMETHOD(device_probe, granttable_probe), + DEVMETHOD(device_attach, granttable_attach), + + DEVMETHOD_END +}; + +DEFINE_CLASS_0(granttable, granttable_driver, granttable_methods, 0); +devclass_t granttable_devclass; + +DRIVER_MODULE_ORDERED(granttable, xenpv, granttable_driver, granttable_devclass, + NULL, NULL, SI_ORDER_FIRST); diff --git a/sys/x86/xen/xenpv.c b/sys/x86/xen/xenpv.c index 9dd5db4a23be..bdda88374f27 100644 --- a/sys/x86/xen/xenpv.c +++ b/sys/x86/xen/xenpv.c @@ -66,15 +66,6 @@ static int xenpv_attach(device_t dev) { device_t child; - int error; - - /* Initialize grant table before any Xen specific device is attached */ - error = gnttab_init(dev); - if (error != 0) { - device_printf(dev, "error initializing grant table: %d\n", - error); - return (error); - } /* * Let our child drivers identify any child devices that they diff --git a/sys/xen/gnttab.h b/sys/xen/gnttab.h index afbe600607a0..d0a44aeabfae 100644 --- a/sys/xen/gnttab.h +++ b/sys/xen/gnttab.h @@ -51,8 +51,6 @@ struct gnttab_free_callback { uint16_t count; }; -int gnttab_init(device_t); - /* * Allocate a grant table reference and return it in *result. Returns * zero on success or errno on error. From 23ca39cf615c91a2397960dce2cd83a91fb762fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Roger=20Pau=20Monn=C3=A9?= Date: Wed, 10 Dec 2014 11:42:02 +0000 Subject: [PATCH 06/13] xen: mask event channels while binding them to a vCPU Mask the event channel source before trying to bind it to a CPU, this prevents stray interrupts from firing while assigning them and hitting the KASSERT in xen_intr_handle_upcall. Sponsored by: Citrix Systems R&D --- sys/x86/xen/xen_intr.c | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/sys/x86/xen/xen_intr.c b/sys/x86/xen/xen_intr.c index 7fc51227692a..ff2544019601 100644 --- a/sys/x86/xen/xen_intr.c +++ b/sys/x86/xen/xen_intr.c @@ -851,7 +851,7 @@ xen_intr_assign_cpu(struct intsrc *base_isrc, u_int apic_id) struct evtchn_bind_vcpu bind_vcpu; struct xenisrc *isrc; u_int to_cpu, vcpu_id; - int error; + int error, masked; #ifdef XENHVM if (xen_vector_callback_enabled == 0) @@ -869,6 +869,11 @@ xen_intr_assign_cpu(struct intsrc *base_isrc, u_int apic_id) return (EINVAL); } + /* + * Mask the event channel while binding it to prevent interrupt + * delivery with an inconsistent state in isrc->xi_cpu. + */ + masked = evtchn_test_and_set_mask(isrc->xi_port); if ((isrc->xi_type == EVTCHN_TYPE_VIRQ) || (isrc->xi_type == EVTCHN_TYPE_IPI)) { /* @@ -879,29 +884,25 @@ xen_intr_assign_cpu(struct intsrc *base_isrc, u_int apic_id) evtchn_cpu_mask_port(isrc->xi_cpu, isrc->xi_port); isrc->xi_cpu = to_cpu; evtchn_cpu_unmask_port(isrc->xi_cpu, isrc->xi_port); - mtx_unlock(&xen_intr_isrc_lock); - return (0); + goto out; } bind_vcpu.port = isrc->xi_port; bind_vcpu.vcpu = vcpu_id; - /* - * Allow interrupts to be fielded on the new VCPU before - * we ask the hypervisor to deliver them there. - */ - evtchn_cpu_unmask_port(to_cpu, isrc->xi_port); error = HYPERVISOR_event_channel_op(EVTCHNOP_bind_vcpu, &bind_vcpu); if (isrc->xi_cpu != to_cpu) { if (error == 0) { /* Commit to new binding by removing the old one. */ evtchn_cpu_mask_port(isrc->xi_cpu, isrc->xi_port); isrc->xi_cpu = to_cpu; - } else { - /* Roll-back to previous binding. */ - evtchn_cpu_mask_port(to_cpu, isrc->xi_port); + evtchn_cpu_unmask_port(isrc->xi_cpu, isrc->xi_port); } } + +out: + if (masked == 0) + evtchn_unmask_port(isrc->xi_port); mtx_unlock(&xen_intr_isrc_lock); return (0); #else From f229f35db70f9a4bfac12c49e91bd9dd56a4975e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Roger=20Pau=20Monn=C3=A9?= Date: Wed, 10 Dec 2014 13:25:21 +0000 Subject: [PATCH 07/13] xen/intr: balance dynamic interrupts across available vCPUs By default Xen binds all event channels to vCPU#0, and FreeBSD only shuffles the interrupt sources once, at the end of the boot process. Since new event channels might be created after this point (because new devices or backends are added), try to automatically shuffle them at creation time. This does not affect VIRQ or IPI event channels, that are already bound to a specific vCPU as requested by the caller. Sponsored by: Citrix Systems R&D --- sys/x86/xen/xen_intr.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/sys/x86/xen/xen_intr.c b/sys/x86/xen/xen_intr.c index ff2544019601..03ccd7ceb8a2 100644 --- a/sys/x86/xen/xen_intr.c +++ b/sys/x86/xen/xen_intr.c @@ -425,6 +425,17 @@ xen_intr_bind_isrc(struct xenisrc **isrcp, evtchn_port_t local_port, /* Assign the opaque handler (the event channel port) */ *port_handlep = &isrc->xi_port; +#ifdef SMP + if (type == EVTCHN_TYPE_PORT) { + /* + * By default all interrupts are assigned to vCPU#0 + * unless specified otherwise, so shuffle them to balance + * the interrupt load. + */ + xen_intr_assign_cpu(&isrc->xi_intsrc, intr_next_cpu()); + } +#endif + if (filter == NULL && handler == NULL) { /* * No filter/handler provided, leave the event channel From be3a49ee62b6af938565ef159b535aea59a92f16 Mon Sep 17 00:00:00 2001 From: Edward Tomasz Napierala Date: Wed, 10 Dec 2014 14:14:16 +0000 Subject: [PATCH 08/13] Add fstyp(8). This utility, named after its SVR4 counterpart, detects filesystems. It differs from file(1) in that it gives machine-parseable output, it outputs filesystem labels, doesn't get confused by other formats metadata, and runs in Capsicum sandbox. Differential Revision: https://reviews.freebsd.org/D1255 Relnotes: yes Sponsored by: The FreeBSD Foundation --- contrib/file/doc/file.man | 3 +- sbin/mount/mount.8 | 3 +- usr.sbin/Makefile | 1 + usr.sbin/fstyp/Makefile | 9 ++ usr.sbin/fstyp/cd9660.c | 72 +++++++++++++ usr.sbin/fstyp/ext2fs.c | 90 ++++++++++++++++ usr.sbin/fstyp/fstyp.8 | 97 ++++++++++++++++++ usr.sbin/fstyp/fstyp.c | 210 ++++++++++++++++++++++++++++++++++++++ usr.sbin/fstyp/fstyp.h | 46 +++++++++ usr.sbin/fstyp/msdosfs.c | 183 +++++++++++++++++++++++++++++++++ usr.sbin/fstyp/msdosfs.h | 140 +++++++++++++++++++++++++ usr.sbin/fstyp/ntfs.c | 165 ++++++++++++++++++++++++++++++ usr.sbin/fstyp/ufs.c | 109 ++++++++++++++++++++ 13 files changed, 1126 insertions(+), 2 deletions(-) create mode 100644 usr.sbin/fstyp/Makefile create mode 100644 usr.sbin/fstyp/cd9660.c create mode 100644 usr.sbin/fstyp/ext2fs.c create mode 100644 usr.sbin/fstyp/fstyp.8 create mode 100644 usr.sbin/fstyp/fstyp.c create mode 100644 usr.sbin/fstyp/fstyp.h create mode 100644 usr.sbin/fstyp/msdosfs.c create mode 100644 usr.sbin/fstyp/msdosfs.h create mode 100644 usr.sbin/fstyp/ntfs.c create mode 100644 usr.sbin/fstyp/ufs.c diff --git a/contrib/file/doc/file.man b/contrib/file/doc/file.man index 361188e13998..8e403bef897c 100644 --- a/contrib/file/doc/file.man +++ b/contrib/file/doc/file.man @@ -1,5 +1,5 @@ .\" $File: file.man,v 1.106 2014/03/07 23:11:51 christos Exp $ -.Dd January 30, 2014 +.Dd December 3, 2014 .Dt FILE __CSECTION__ .Os .Sh NAME @@ -385,6 +385,7 @@ options. .Xr hexdump 1 , .Xr od 1 , .Xr strings 1 , +.Xr fstyp 8 .Sh STANDARDS CONFORMANCE This program is believed to exceed the System V Interface Definition of FILE(CMD), as near as one can determine from the vague language diff --git a/sbin/mount/mount.8 b/sbin/mount/mount.8 index 12c25add90e6..aa7acfd61031 100644 --- a/sbin/mount/mount.8 +++ b/sbin/mount/mount.8 @@ -28,7 +28,7 @@ .\" @(#)mount.8 8.8 (Berkeley) 6/16/94 .\" $FreeBSD$ .\" -.Dd November 22, 2014 +.Dd December 3, 2014 .Dt MOUNT 8 .Os .Sh NAME @@ -549,6 +549,7 @@ support for a particular file system might be provided either on a static .Xr fstab 5 , .Xr procfs 5 , .Xr automount 8 , +.Xr fstyp 8 , .Xr kldload 8 , .Xr mount_cd9660 8 , .Xr mount_msdosfs 8 , diff --git a/usr.sbin/Makefile b/usr.sbin/Makefile index df9f8674793d..7c444816f42d 100644 --- a/usr.sbin/Makefile +++ b/usr.sbin/Makefile @@ -29,6 +29,7 @@ SUBDIR= adduser \ extattr \ extattrctl \ fifolog \ + fstyp \ fwcontrol \ getfmac \ getpmac \ diff --git a/usr.sbin/fstyp/Makefile b/usr.sbin/fstyp/Makefile new file mode 100644 index 000000000000..d0b14d1bc795 --- /dev/null +++ b/usr.sbin/fstyp/Makefile @@ -0,0 +1,9 @@ +# $FreeBSD$ + +PROG= fstyp +SRCS= fstyp.c ext2fs.c cd9660.c msdosfs.c ntfs.c ufs.c +MAN= fstyp.8 + +WARNS= 6 + +.include diff --git a/usr.sbin/fstyp/cd9660.c b/usr.sbin/fstyp/cd9660.c new file mode 100644 index 000000000000..26ea6942d6bb --- /dev/null +++ b/usr.sbin/fstyp/cd9660.c @@ -0,0 +1,72 @@ +/*- + * Copyright (c) 2004 Pawel Jakub Dawidek + * Copyright (c) 2014 The FreeBSD Foundation + * All rights reserved. + * + * This software was developed by Edward Tomasz Napierala under sponsorship + * from the FreeBSD Foundation. + * + * 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, 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 AUTHORS 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 AUTHORS 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 +__FBSDID("$FreeBSD$"); + +#include +#include +#include + +#include "fstyp.h" + +#define G_LABEL_ISO9660_DIR "iso9660" + +#define ISO9660_MAGIC "\x01" "CD001" "\x01\x00" +#define ISO9660_OFFSET 0x8000 +#define VOLUME_LEN 32 + +int +fstyp_cd9660(FILE *fp, char *label, size_t size) +{ + char *sector, *volume; + int i; + + sector = read_buf(fp, ISO9660_OFFSET, 512); + if (sector == NULL) + return (1); + if (bcmp(sector, ISO9660_MAGIC, sizeof(ISO9660_MAGIC) - 1) != 0) { + free(sector); + return (1); + } + volume = sector + 0x28; + bzero(label, size); + strlcpy(label, volume, MIN(size, VOLUME_LEN)); + free(sector); + for (i = size - 1; i > 0; i--) { + if (label[i] == '\0') + continue; + else if (label[i] == ' ') + label[i] = '\0'; + else + break; + } + return (0); +} diff --git a/usr.sbin/fstyp/ext2fs.c b/usr.sbin/fstyp/ext2fs.c new file mode 100644 index 000000000000..df9e66e9155a --- /dev/null +++ b/usr.sbin/fstyp/ext2fs.c @@ -0,0 +1,90 @@ +/*- + * Copyright (c) 2005 Stanislav Sedov + * Copyright (c) 2014 The FreeBSD Foundation + * All rights reserved. + * + * This software was developed by Edward Tomasz Napierala under sponsorship + * from the FreeBSD Foundation. + * + * 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, 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 +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include + +#include "fstyp.h" + +#define EXT2FS_SB_OFFSET 1024 +#define EXT2_SUPER_MAGIC 0xef53 +#define EXT2_DYNAMIC_REV 1 + +typedef struct e2sb { + uint8_t fake1[56]; + uint16_t s_magic; + uint8_t fake2[18]; + uint32_t s_rev_level; + uint8_t fake3[40]; + char s_volume_name[16]; +} e2sb_t; + +int +fstyp_ext2fs(FILE *fp, char *label, size_t size) +{ + e2sb_t *fs; + char *s_volume_name; + + fs = (e2sb_t *)read_buf(fp, EXT2FS_SB_OFFSET, 512); + if (fs == NULL) + return (1); + + /* Check for magic and versio n*/ + if (fs->s_magic == EXT2_SUPER_MAGIC && + fs->s_rev_level == EXT2_DYNAMIC_REV) { + //G_LABEL_DEBUG(1, "ext2fs file system detected on %s.", + // pp->name); + } else { + free(fs); + return (1); + } + + s_volume_name = fs->s_volume_name; + /* Terminate label */ + s_volume_name[sizeof(fs->s_volume_name) - 1] = '\0'; + + if (s_volume_name[0] == '/') + s_volume_name += 1; + + /* Check for volume label */ + if (s_volume_name[0] == '\0') { + free(fs); + return (1); + } + + strlcpy(label, s_volume_name, size); + + return (0); +} diff --git a/usr.sbin/fstyp/fstyp.8 b/usr.sbin/fstyp/fstyp.8 new file mode 100644 index 000000000000..a2594c5b7ca4 --- /dev/null +++ b/usr.sbin/fstyp/fstyp.8 @@ -0,0 +1,97 @@ +.\" Copyright (c) 2014 The FreeBSD Foundation +.\" All rights reserved. +.\" +.\" This software was developed by Edward Tomasz Napierala under sponsorship +.\" from the FreeBSD Foundation. +.\" +.\" 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, 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 AUTHORS 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 AUTHORS 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. +.\" +.\" $FreeBSD$ +.\" +.Dd December 6, 2014 +.Dt FSTYP 8 +.Os +.Sh NAME +.Nm fstyp +.Nd determine filesystem type +.Sh SYNOPSIS +.Nm +.Op Fl l +.Op Fl s +.Ar special +.Sh DESCRIPTION +The +.Nm +utility is used to determine the filesystem type on a given device. +It can recognize ISO-9660, Ext2, FAT, NTFS, and UFS filesystems. +The filesystem name is printed to the standard output +as, respectively, +.Li cd9660 , +.Li ext2fs , +.Li msdosfs , +.Li ntfs , +or +.Li ufs . +.Pp +Because +.Nm +is built specifically to detect filesystem types, it differs from +.Xr file 1 +in several ways. +The output is machine-parsable, filesystem labels are supported, +and only filesystems are identified. +Security is improved with +.Xr capsicum 4 . +.Pp +These options are available: +.Bl -tag -width ".Fl l" +.It Fl l +In addition to filesystem type, print filesystem label if available. +.It Fl s +Ignore file type. +By default, +.Nm +only works on regular files and disk-like device nodes. +Trying to read other file types might have unexpected consequences or hang +indefinitely. +.El +.Sh EXIT STATUS +The +.Nm +utility exits 0 on success, and >0 if an error occurs or the filesystem +type is not recognized. +.Sh SEE ALSO +.Xr file 1 , +.Xr capsicum 4 , +.Xr glabel 8 , +.Xr mount 8 +.Sh HISTORY +The +.Nm +command appeared in +.Fx 11.0 . +.Sh AUTHORS +The +.Nm +utility was developed by +.An Edward Tomasz Napierala Aq Mt trasz@FreeBSD.org +under sponsorship from the FreeBSD Foundation. diff --git a/usr.sbin/fstyp/fstyp.c b/usr.sbin/fstyp/fstyp.c new file mode 100644 index 000000000000..d6a48f61d63a --- /dev/null +++ b/usr.sbin/fstyp/fstyp.c @@ -0,0 +1,210 @@ +/*- + * Copyright (c) 2014 The FreeBSD Foundation + * All rights reserved. + * + * This software was developed by Edward Tomasz Napierala under sponsorship + * from the FreeBSD Foundation. + * + * 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, 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 +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "fstyp.h" + +#define LABEL_LEN 256 + +typedef int (*fstyp_function)(FILE *, char *, size_t); + +static struct { + const char *name; + fstyp_function function; +} fstypes[] = { + { "cd9660", &fstyp_cd9660 }, + { "ext2fs", &fstyp_ext2fs }, + { "msdosfs", &fstyp_msdosfs }, + { "ntfs", &fstyp_ntfs }, + { "ufs", &fstyp_ufs }, + { NULL, NULL } +}; + +void * +read_buf(FILE *fp, off_t off, size_t len) +{ + int error; + size_t nread; + void *buf; + + error = fseek(fp, off, SEEK_SET); + if (error != 0) { + warn("cannot seek to %jd", (uintmax_t)off); + return (NULL); + } + + buf = malloc(len); + if (buf == 0) { + warn("cannot malloc %zd bytes of memory", len); + return (NULL); + } + + nread = fread(buf, len, 1, fp); + if (nread != 1) { + free(buf); + if (feof(fp) == 0) + warn("fread"); + return (NULL); + } + + return (buf); +} + +char * +checked_strdup(const char *s) +{ + char *c; + + c = strdup(s); + if (c == NULL) + err(1, "strdup"); + return (c); +} + +static void +usage(void) +{ + + fprintf(stderr, "usage: fstyp [-l][-s] special\n"); + exit(1); +} + +static void +type_check(const char *path, FILE *fp) +{ + int error, fd; + off_t mediasize; + struct stat sb; + + fd = fileno(fp); + + error = fstat(fd, &sb); + if (error != 0) + err(1, "%s: fstat", path); + + if (S_ISREG(sb.st_mode)) + return; + + error = ioctl(fd, DIOCGMEDIASIZE, &mediasize); + if (error != 0) + errx(1, "%s: not a disk", path); +} + +int +main(int argc, char **argv) +{ + int ch, error, i, nbytes; + bool ignore_type = false, show_label = false; + char label[LABEL_LEN + 1], strvised[LABEL_LEN * 4 + 1]; + char *path; + FILE *fp; + fstyp_function fstyp_f; + + while ((ch = getopt(argc, argv, "ls")) != -1) { + switch (ch) { + case 'l': + show_label = true; + break; + case 's': + ignore_type = true; + break; + default: + usage(); + } + } + + argc -= optind; + argv += optind; + if (argc != 1) + usage(); + + path = argv[0]; + + fp = fopen(path, "r"); + if (fp == NULL) + err(1, "%s", path); + + error = cap_enter(); + if (error != 0 && errno != ENOSYS) + err(1, "cap_enter"); + + if (ignore_type == false) + type_check(path, fp); + + memset(label, '\0', sizeof(label)); + + for (i = 0;; i++) { + fstyp_f = fstypes[i].function; + if (fstyp_f == NULL) + break; + + error = fstyp_f(fp, label, sizeof(label)); + if (error == 0) + break; + } + + if (fstypes[i].name == NULL) { + warnx("%s: filesystem not recognized", path); + return (1); + } + + if (show_label && label[0] != '\0') { + /* + * XXX: I'd prefer VIS_HTTPSTYLE, but it unconditionally + * encodes spaces. + */ + nbytes = strsnvis(strvised, sizeof(strvised), label, + VIS_GLOB | VIS_NL, "\"'$"); + if (nbytes == -1) + err(1, "strsnvis"); + + printf("%s %s\n", fstypes[i].name, strvised); + } else { + printf("%s\n", fstypes[i].name); + } + + return (0); +} diff --git a/usr.sbin/fstyp/fstyp.h b/usr.sbin/fstyp/fstyp.h new file mode 100644 index 000000000000..4474ffe6f858 --- /dev/null +++ b/usr.sbin/fstyp/fstyp.h @@ -0,0 +1,46 @@ +/*- + * Copyright (c) 2014 The FreeBSD Foundation + * All rights reserved. + * + * This software was developed by Edward Tomasz Napierala under sponsorship + * from the FreeBSD Foundation. + * + * 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, 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. + * + * $FreeBSD$ + */ + +#ifndef FSTYP_H +#define FSTYP_H + +#define MIN(a,b) (((a)<(b))?(a):(b)) + +void *read_buf(FILE *fp, off_t off, size_t len); +char *checked_strdup(const char *s); + +int fstyp_cd9660(FILE *fp, char *label, size_t size); +int fstyp_ext2fs(FILE *fp, char *label, size_t size); +int fstyp_msdosfs(FILE *fp, char *label, size_t size); +int fstyp_ntfs(FILE *fp, char *label, size_t size); +int fstyp_ufs(FILE *fp, char *label, size_t size); + +#endif /* !FSTYP_H */ diff --git a/usr.sbin/fstyp/msdosfs.c b/usr.sbin/fstyp/msdosfs.c new file mode 100644 index 000000000000..b299243aebd1 --- /dev/null +++ b/usr.sbin/fstyp/msdosfs.c @@ -0,0 +1,183 @@ +/*- + * Copyright (c) 2004 Pawel Jakub Dawidek + * Copyright (c) 2006 Tobias Reifenberger + * Copyright (c) 2014 The FreeBSD Foundation + * All rights reserved. + * + * This software was developed by Edward Tomasz Napierala under sponsorship + * from the FreeBSD Foundation. + * + * 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, 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 AUTHORS 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 AUTHORS 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 +__FBSDID("$FreeBSD$"); + +#include +#include +#include + +#include "fstyp.h" +#include "msdosfs.h" + +#define LABEL_NO_NAME "NO NAME " + +int +fstyp_msdosfs(FILE *fp, char *label, size_t size) +{ + FAT_BSBPB *pfat_bsbpb; + FAT32_BSBPB *pfat32_bsbpb; + FAT_DES *pfat_entry; + uint8_t *sector0, *sector; + uint32_t i; + + sector0 = NULL; + sector = NULL; + + /* Load 1st sector with boot sector and boot parameter block. */ + sector0 = (uint8_t *)read_buf(fp, 0, 512); + if (sector0 == NULL) + return (1); + + /* Check for the FAT boot sector signature. */ + if (sector0[510] != 0x55 || sector0[511] != 0xaa) { + goto error; + } + + /* + * Test if this is really a FAT volume and determine the FAT type. + */ + + pfat_bsbpb = (FAT_BSBPB *)sector0; + pfat32_bsbpb = (FAT32_BSBPB *)sector0; + + if (UINT16BYTES(pfat_bsbpb->BPB_FATSz16) != 0) { + /* + * If the BPB_FATSz16 field is not zero and the string "FAT" is + * at the right place, this should be a FAT12 or FAT16 volume. + */ + if (strncmp(pfat_bsbpb->BS_FilSysType, "FAT", 3) != 0) { + goto error; + } + + /* A volume with no name should have "NO NAME " as label. */ + if (strncmp(pfat_bsbpb->BS_VolLab, LABEL_NO_NAME, + sizeof(pfat_bsbpb->BS_VolLab)) == 0) { + goto endofchecks; + } + strlcpy(label, pfat_bsbpb->BS_VolLab, + MIN(size, sizeof(pfat_bsbpb->BS_VolLab) + 1)); + } else if (UINT32BYTES(pfat32_bsbpb->BPB_FATSz32) != 0) { + uint32_t fat_FirstDataSector, fat_BytesPerSector, offset; + + /* + * If the BPB_FATSz32 field is not zero and the string "FAT" is + * at the right place, this should be a FAT32 volume. + */ + if (strncmp(pfat32_bsbpb->BS_FilSysType, "FAT", 3) != 0) { + goto error; + } + + /* + * If the volume label is not "NO NAME " we're done. + */ + if (strncmp(pfat32_bsbpb->BS_VolLab, LABEL_NO_NAME, + sizeof(pfat32_bsbpb->BS_VolLab)) != 0) { + strlcpy(label, pfat32_bsbpb->BS_VolLab, + MIN(size, sizeof(pfat32_bsbpb->BS_VolLab) + 1)); + goto endofchecks; + } + + /* + * If the volume label "NO NAME " is in the boot sector, the + * label of FAT32 volumes may be stored as a special entry in + * the root directory. + */ + fat_FirstDataSector = + UINT16BYTES(pfat32_bsbpb->BPB_RsvdSecCnt) + + (pfat32_bsbpb->BPB_NumFATs * + UINT32BYTES(pfat32_bsbpb->BPB_FATSz32)); + fat_BytesPerSector = UINT16BYTES(pfat32_bsbpb->BPB_BytsPerSec); + + // fat_FirstDataSector, fat_BytesPerSector); + + for (offset = fat_BytesPerSector * fat_FirstDataSector;; + offset += fat_BytesPerSector) { + sector = (uint8_t *)read_buf(fp, offset, fat_BytesPerSector); + if (sector == NULL) + goto error; + + pfat_entry = (FAT_DES *)sector; + do { + /* No more entries available. */ + if (pfat_entry->DIR_Name[0] == 0) { + goto endofchecks; + } + + /* Skip empty or long name entries. */ + if (pfat_entry->DIR_Name[0] == 0xe5 || + (pfat_entry->DIR_Attr & + FAT_DES_ATTR_LONG_NAME) == + FAT_DES_ATTR_LONG_NAME) { + continue; + } + + /* + * The name of the entry is the volume label if + * ATTR_VOLUME_ID is set. + */ + if (pfat_entry->DIR_Attr & + FAT_DES_ATTR_VOLUME_ID) { + strlcpy(label, pfat_entry->DIR_Name, + MIN(size, + sizeof(pfat_entry->DIR_Name) + 1)); + goto endofchecks; + } + } while((uint8_t *)(++pfat_entry) < + (uint8_t *)(sector + fat_BytesPerSector)); + free(sector); + } + } else { + goto error; + } + +endofchecks: + for (i = size - 1; i > 0; i--) { + if (label[i] == '\0') + continue; + else if (label[i] == ' ') + label[i] = '\0'; + else + break; + } + + free(sector0); + free(sector); + + return (0); + +error: + free(sector0); + free(sector); + + return (1); +} diff --git a/usr.sbin/fstyp/msdosfs.h b/usr.sbin/fstyp/msdosfs.h new file mode 100644 index 000000000000..a04b87fe9706 --- /dev/null +++ b/usr.sbin/fstyp/msdosfs.h @@ -0,0 +1,140 @@ +/*- + * Copyright (c) 2006 Tobias Reifenberger + * 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, 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 AUTHORS 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 AUTHORS 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. + * + * $FreeBSD$ + */ + +#include + +/* + * Conversion macros for little endian encoded unsigned integers + * in byte streams to the local unsigned integer format. + */ +#define UINT16BYTES(p) ((uint32_t)((p)[0] + (256*(p)[1]))) +#define UINT32BYTES(p) ((uint32_t)((p)[0] + (256*(p)[1]) + \ + (65536*(p)[2]) + (16777216*(p)[3]))) + +/* + * All following structures are according to: + * + * Microsoft Extensible Firmware Initiative FAT32 File System Specification + * FAT: General Overview of On-Disk Format + * Version 1.03, December 6, 2000 + * Microsoft Corporation + */ + +/* + * FAT boot sector and boot parameter block for + * FAT12 and FAT16 volumes + */ +typedef struct fat_bsbpb { + /* common fields */ + uint8_t BS_jmpBoot[3]; + uint8_t BS_OEMName[8]; + uint8_t BPB_BytsPerSec[2]; + uint8_t BPB_SecPerClus; + uint8_t BPB_RsvdSecCnt[2]; + uint8_t BPB_NumFATs; + uint8_t BPB_RootEntCnt[2]; + uint8_t BPB_TotSec16[2]; + uint8_t BPB_Media; + uint8_t BPB_FATSz16[2]; + uint8_t BPB_SecPerTrack[2]; + uint8_t BPB_NumHeads[2]; + uint8_t BPB_HiddSec[4]; + uint8_t BPB_TotSec32[4]; + /* FAT12/FAT16 only fields */ + uint8_t BS_DrvNum; + uint8_t BS_Reserved1; + uint8_t BS_BootSig; + uint8_t BS_VolID[4]; + uint8_t BS_VolLab[11]; + uint8_t BS_FilSysType[8]; +} FAT_BSBPB; /* 62 bytes */ + +/* + * FAT boot sector and boot parameter block for + * FAT32 volumes + */ +typedef struct fat32_bsbpb { + /* common fields */ + uint8_t BS_jmpBoot[3]; + uint8_t BS_OEMName[8]; + uint8_t BPB_BytsPerSec[2]; + uint8_t BPB_SecPerClus; + uint8_t BPB_RsvdSecCnt[2]; + uint8_t BPB_NumFATs; + uint8_t BPB_RootEntCnt[2]; + uint8_t BPB_TotSec16[2]; + uint8_t BPB_Media; + uint8_t BPB_FATSz16[2]; + uint8_t BPB_SecPerTrack[2]; + uint8_t BPB_NumHeads[2]; + uint8_t BPB_HiddSec[4]; + uint8_t BPB_TotSec32[4]; + /* FAT32 only fields */ + uint8_t BPB_FATSz32[4]; + uint8_t BPB_ExtFlags[2]; + uint8_t BPB_FSVer[2]; + uint8_t BPB_RootClus[4]; + uint8_t BPB_FSInfo[2]; + uint8_t BPB_BkBootSec[2]; + uint8_t BPB_Reserved[12]; + uint8_t BS_DrvNum; + uint8_t BS_Reserved1; + uint8_t BS_BootSig; + uint8_t BS_VolID[4]; + uint8_t BS_VolLab[11]; + uint8_t BS_FilSysType[8]; +} FAT32_BSBPB; /* 90 bytes */ + +/* + * FAT directory entry structure + */ +#define FAT_DES_ATTR_READ_ONLY 0x01 +#define FAT_DES_ATTR_HIDDEN 0x02 +#define FAT_DES_ATTR_SYSTEM 0x04 +#define FAT_DES_ATTR_VOLUME_ID 0x08 +#define FAT_DES_ATTR_DIRECTORY 0x10 +#define FAT_DES_ATTR_ARCHIVE 0x20 +#define FAT_DES_ATTR_LONG_NAME (FAT_DES_ATTR_READ_ONLY | \ + FAT_DES_ATTR_HIDDEN | \ + FAT_DES_ATTR_SYSTEM | \ + FAT_DES_ATTR_VOLUME_ID) + +typedef struct fat_des { + uint8_t DIR_Name[11]; + uint8_t DIR_Attr; + uint8_t DIR_NTRes; + uint8_t DIR_CrtTimeTenth; + uint8_t DIR_CrtTime[2]; + uint8_t DIR_CrtDate[2]; + uint8_t DIR_LstAccDate[2]; + uint8_t DIR_FstClusHI[2]; + uint8_t DIR_WrtTime[2]; + uint8_t DIR_WrtDate[2]; + uint8_t DIR_FstClusLO[2]; + uint8_t DIR_FileSize[4]; +} FAT_DES; diff --git a/usr.sbin/fstyp/ntfs.c b/usr.sbin/fstyp/ntfs.c new file mode 100644 index 000000000000..582f6b955e21 --- /dev/null +++ b/usr.sbin/fstyp/ntfs.c @@ -0,0 +1,165 @@ +/*- + * Copyright (c) 2005 Takanori Watanabe + * Copyright (c) 2014 The FreeBSD Foundation + * All rights reserved. + * + * This software was developed by Edward Tomasz Napierala under sponsorship + * from the FreeBSD Foundation. + * + * 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, 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 +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include + +#include "fstyp.h" + +#define NTFS_A_VOLUMENAME 0x60 +#define NTFS_FILEMAGIC ((uint32_t)(0x454C4946)) +#define NTFS_VOLUMEINO 3 + +#define G_LABEL_NTFS_DIR "ntfs" + +struct ntfs_attr { + uint32_t a_type; + uint32_t reclen; + uint8_t a_flag; + uint8_t a_namelen; + uint8_t a_nameoff; + uint8_t reserved1; + uint8_t a_compression; + uint8_t reserved2; + uint16_t a_index; + uint16_t a_datalen; + uint16_t reserved3; + uint16_t a_dataoff; + uint16_t a_indexed; +} __packed; + +struct ntfs_filerec { + uint32_t fr_hdrmagic; + uint16_t fr_hdrfoff; + uint16_t fr_hdrfnum; + uint8_t reserved[8]; + uint16_t fr_seqnum; + uint16_t fr_nlink; + uint16_t fr_attroff; + uint16_t fr_flags; + uint32_t fr_size; + uint32_t fr_allocated; + uint64_t fr_mainrec; + uint16_t fr_attrnum; +} __packed; + +struct ntfs_bootfile { + uint8_t reserved1[3]; + uint8_t bf_sysid[8]; + uint16_t bf_bps; + uint8_t bf_spc; + uint8_t reserved2[7]; + uint8_t bf_media; + uint8_t reserved3[2]; + uint16_t bf_spt; + uint16_t bf_heads; + uint8_t reserver4[12]; + uint64_t bf_spv; + uint64_t bf_mftcn; + uint64_t bf_mftmirrcn; + int8_t bf_mftrecsz; + uint32_t bf_ibsz; + uint32_t bf_volsn; +} __packed; + +int +fstyp_ntfs(FILE *fp, char *label, size_t size) +{ + struct ntfs_bootfile *bf; + struct ntfs_filerec *fr; + struct ntfs_attr *atr; + off_t voloff; + char *filerecp, *ap; + int8_t mftrecsz; + char vnchar; + int recsize, j; + + filerecp = NULL; + + bf = (struct ntfs_bootfile *)read_buf(fp, 0, 512); + if (bf == NULL || strncmp(bf->bf_sysid, "NTFS ", 8) != 0) + return (1); + + mftrecsz = bf->bf_mftrecsz; + recsize = (mftrecsz > 0) ? (mftrecsz * bf->bf_bps * bf->bf_spc) : (1 << -mftrecsz); + + voloff = bf->bf_mftcn * bf->bf_spc * bf->bf_bps + + recsize * NTFS_VOLUMEINO; + + filerecp = read_buf(fp, voloff, recsize); + if (filerecp == NULL) + goto fail; + fr = (struct ntfs_filerec *)filerecp; + + if (fr->fr_hdrmagic != NTFS_FILEMAGIC) + goto fail; + + for (ap = filerecp + fr->fr_attroff; + atr = (struct ntfs_attr *)ap, (int)atr->a_type != -1; + ap += atr->reclen) { + if (atr->a_type == NTFS_A_VOLUMENAME) { + if(atr->a_datalen >= size *2){ + goto fail; + } + /* + *UNICODE to ASCII. + * Should we need to use iconv(9)? + */ + for (j = 0; j < atr->a_datalen; j++) { + vnchar = *(ap + atr->a_dataoff + j); + if (j & 1) { + if (vnchar) { + goto fail; + } + } else { + label[j / 2] = vnchar; + } + } + label[j / 2] = 0; + break; + } + } + + free(bf); + free(filerecp); + + return (0); + +fail: + free(bf); + free(filerecp); + + return (1); +} diff --git a/usr.sbin/fstyp/ufs.c b/usr.sbin/fstyp/ufs.c new file mode 100644 index 000000000000..8b27ca00fe43 --- /dev/null +++ b/usr.sbin/fstyp/ufs.c @@ -0,0 +1,109 @@ +/*- + * Copyright (c) 2002, 2003 Gordon Tetlow + * Copyright (c) 2006 Pawel Jakub Dawidek + * Copyright (c) 2014 The FreeBSD Foundation + * All rights reserved. + * + * This software was developed by Edward Tomasz Napierala under sponsorship + * from the FreeBSD Foundation. + * + * 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, 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 AUTHORS 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 AUTHORS 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 +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include + +#include +#include + +#include "fstyp.h" + +static const int superblocks[] = SBLOCKSEARCH; + +int +fstyp_ufs(FILE *fp, char *label, size_t labelsize) +{ + int sb, superblock; + struct fs *fs; + + /* + * Walk through the standard places that superblocks hide and look + * for UFS magic. If we find magic, then check that the size in the + * superblock corresponds to the size of the underlying provider. + * Finally, look for a volume label and create an appropriate + * provider based on that. + */ + for (sb = 0; (superblock = superblocks[sb]) != -1; sb++) { + fs = (struct fs *)read_buf(fp, superblock, SBLOCKSIZE); + if (fs == NULL) + continue; + /* + * Check for magic. We also need to check if file system size is equal + * to providers size, because sysinstall(8) used to bogusly put first + * partition at offset 0 instead of 16, and glabel/ufs would find file + * system on slice instead of partition. + */ +#ifdef notyet + if (fs->fs_magic == FS_UFS1_MAGIC && fs->fs_fsize > 0 && + ((pp->mediasize / fs->fs_fsize == fs->fs_old_size) || + (pp->mediasize / fs->fs_fsize == fs->fs_providersize))) { + /* Valid UFS1. */ + } else if (fs->fs_magic == FS_UFS2_MAGIC && fs->fs_fsize > 0 && + ((pp->mediasize / fs->fs_fsize == fs->fs_size) || + (pp->mediasize / fs->fs_fsize == fs->fs_providersize))) { + /* Valid UFS2. */ + } else { + g_free(fs); + continue; + } +#else + if (fs->fs_magic == FS_UFS1_MAGIC && fs->fs_fsize > 0) { + /* Valid UFS1. */ + } else if (fs->fs_magic == FS_UFS2_MAGIC && fs->fs_fsize > 0) { + /* Valid UFS2. */ + } else { + free(fs); + continue; + } +#endif + + if (fs->fs_sblockloc != superblock || fs->fs_ncg < 1 || + fs->fs_bsize < MINBSIZE || + (size_t)fs->fs_bsize < sizeof(struct fs)) { + free(fs); + continue; + } + + strlcpy(label, fs->fs_volname, labelsize); + + free(fs); + return (0); + } + + return (1); +} From d0ff09c9c063c829aa15b24b041368bde1c66acd Mon Sep 17 00:00:00 2001 From: Edward Tomasz Napierala Date: Wed, 10 Dec 2014 14:36:44 +0000 Subject: [PATCH 09/13] Add "-media" autofs map, to access data on removable media, such as CD drives or flash keys. It can be enabled by uncommenting a single entry in default /etc/auto_master. It can also be easily modified to use fuse-based filesystems instead of in-kernel ones. There is still one deficiency - the mountpoints are permanent, they don't disappear when user removes the media. Fixing it needs some autofs changes. Differential Revision: https://reviews.freebsd.org/D1210 MFC after: 1 month Sponsored by: The FreeBSD Foundation --- etc/auto_master | 3 ++ etc/autofs/Makefile | 2 +- etc/autofs/special_media | 93 +++++++++++++++++++++++++++++++++++ etc/devd.conf | 12 +++++ usr.sbin/autofs/auto_master.5 | 15 +++--- 5 files changed, 118 insertions(+), 7 deletions(-) create mode 100755 etc/autofs/special_media diff --git a/etc/auto_master b/etc/auto_master index 3b3e5dad70b2..2e4db21fe39d 100644 --- a/etc/auto_master +++ b/etc/auto_master @@ -3,3 +3,6 @@ # Automounter master map, see auto_master(5) for details. # /net -hosts -nobrowse,nosuid +# When using the -media special map, make sure to edit devd.conf(5) +# to move the call to "automount -c" out of the comments section. +#/media -media -nosuid diff --git a/etc/autofs/Makefile b/etc/autofs/Makefile index c9eda5073e42..3aa7e0307a74 100644 --- a/etc/autofs/Makefile +++ b/etc/autofs/Makefile @@ -1,6 +1,6 @@ # $FreeBSD$ -FILES= include_ldap special_hosts special_null +FILES= include_ldap special_hosts special_media special_null NO_OBJ= FILESDIR= /etc/autofs diff --git a/etc/autofs/special_media b/etc/autofs/special_media new file mode 100755 index 000000000000..2a654b1d5a9b --- /dev/null +++ b/etc/autofs/special_media @@ -0,0 +1,93 @@ +#!/bin/sh +# +# $FreeBSD$ +# + +# Print newline-separated list of devices available for mounting. +# If there is a filesystem label - use it, otherwise use device name. +print_available() { + local _fstype _fstype_and_label _label _p + + for _p in ${providers}; do + _fstype_and_label="$(fstyp -l "/dev/${_p}" 2> /dev/null)" + if [ $? -ne 0 ]; then + # Ignore devices for which we were unable + # to determine filesystem type. + continue + fi + + _fstype="${_fstype_and_label%% *}" + if [ "${_fstype}" != "${_fstype_and_label}" ]; then + _label="${_fstype_and_label#* }" + echo "${_label}" + continue + fi + + echo "${_p}" + done +} + +# Print a single map entry. +print_one() { + local _fstype _fstype_and_label _label _key _p + + _key="$1" + + _fstype="$(fstyp "/dev/${_key}" 2> /dev/null)" + if [ $? -eq 0 ]; then + echo "-fstype=${_fstype},nosuid :/dev/${_key}" + return + fi + + for _p in ${providers}; do + _fstype_and_label="$(fstyp -l "/dev/${_p}" 2> /dev/null)" + if [ $? -ne 0 ]; then + # Ignore devices for which we were unable + # to determine filesystem type. + continue + fi + + _fstype="${_fstype_and_label%% *}" + if [ "${_fstype}" = "${_fstype_and_label}" ]; then + # No label, try another device. + continue + fi + + _label="${_fstype_and_label#* }" + if [ "${_label}" != "${_key}" ]; then + # Labels don't match, try another device. + continue + fi + + echo "-fstype=${_fstype},nosuid :/dev/${_p}" + done + + # No matching device - don't print anything, autofs will handle it. +} + +# Obtain a list of (geom-provider-name, access-count) pairs, turning this: +# +# z0xfffff80005085d00 [shape=hexagon,label="ada0\nr2w2e3\nerr#0\nsector=512\nstripe=0"]; +# +# Into this: +# +# ada0 r2w2e3 +# +# XXX: It would be easier to use kern.geom.conftxt instead, but it lacks +# access counts. +pairs=$(sysctl kern.geom.confdot | sed -n 's/^.*hexagon,label="\([^\]*\)\\n\([^\]*\).*/\1 \2/p') + +# Obtain a list of GEOM providers that are not already open - not mounted, +# and without other GEOM class, such as gpart, attached. In other words, +# grep for "r0w0e0". Skip providers with names containing slashes; we're +# not interested in geom_label(4) creations. +providers=$(echo "$pairs" | awk '$2 == "r0w0e0" && $1 !~ /\// { print $1 }') + +if [ $# -eq 0 ]; then + print_available + exit 0 +fi + +print_one "$1" +exit 0 + diff --git a/etc/devd.conf b/etc/devd.conf index 12f6931d48ed..742871768572 100644 --- a/etc/devd.conf +++ b/etc/devd.conf @@ -318,4 +318,16 @@ notify 0 { action "/usr/local/etc/rc.d/postgresql restart"; }; +# Discard autofs caches, useful for the -media special map. The one +# second delay is for GEOM to finish tasting. +# +# XXX: We should probably have a devctl(4) event that fires after GEOM +# tasting. +# +notify 100 { + match "system" "DEVFS"; + match "cdev" "(da|mmcsd)[0-9]+"; + action "sleep 1 && /usr/sbin/automount -c"; +}; + */ diff --git a/usr.sbin/autofs/auto_master.5 b/usr.sbin/autofs/auto_master.5 index 8e817fe050d1..baad6407acce 100644 --- a/usr.sbin/autofs/auto_master.5 +++ b/usr.sbin/autofs/auto_master.5 @@ -27,7 +27,7 @@ .\" .\" $FreeBSD$ .\" -.Dd November 21, 2014 +.Dd November 22, 2014 .Dt AUTO_MASTER 5 .Os .Sh NAME @@ -213,14 +213,17 @@ Supported special maps are: .Pp .Bl -tag -width "-hosts" -compact .It Li -hosts -This map queries the remote NFS server and maps exported volumes. -It is traditionally mounted on +Query the remote NFS server and map exported shares. +This map is traditionally mounted on .Pa /net . -It enables access to files on a remote NFS server by accessing +Access to files on a remote NFS server is provided through the .Pa /net/nfs-server-ip/share-name/ -directory, without the need for any further configuration. +directory without any additional configuration. +.It Li -media +Query devices that are not yet mounted, but contain valid filesystems. +Generally used to access files on removable media. .It Li -null -This map prevents the +Prevent .Xr automountd 8 from mounting anything on the mountpoint. .El From 0d958bd47a46c34cdd7435e9133ef4aee4fb128b Mon Sep 17 00:00:00 2001 From: Michael Tuexen Date: Wed, 10 Dec 2014 14:50:57 +0000 Subject: [PATCH 10/13] Fix a typo reported by Lennart Grahl. MFC after: 3 days --- lib/libc/net/sctp_sys_calls.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/libc/net/sctp_sys_calls.c b/lib/libc/net/sctp_sys_calls.c index 91527c353fce..ea66df9d886c 100644 --- a/lib/libc/net/sctp_sys_calls.c +++ b/lib/libc/net/sctp_sys_calls.c @@ -886,7 +886,7 @@ sctp_recvv(int sd, struct sctp_rcvinfo *rcvinfo; struct sctp_nxtinfo *nxtinfo; - if (((info != NULL) && (infolen == NULL)) | + if (((info != NULL) && (infolen == NULL)) || ((info == NULL) && (infolen != NULL) && (*infolen != 0)) || ((info != NULL) && (infotype == NULL))) { errno = EINVAL; From 85859dfe8f8a41c7e139984aaaecd3abdc58e20d Mon Sep 17 00:00:00 2001 From: Andreas Tobler Date: Wed, 10 Dec 2014 18:13:14 +0000 Subject: [PATCH 11/13] Fix build for powerpc(32|64) kernels. --- sys/powerpc/aim/trap.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sys/powerpc/aim/trap.c b/sys/powerpc/aim/trap.c index 8276e96f1936..354c63be4f69 100644 --- a/sys/powerpc/aim/trap.c +++ b/sys/powerpc/aim/trap.c @@ -46,6 +46,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include From a00b2ba8fe73f5f8adbdfe8f407a194d19d66e76 Mon Sep 17 00:00:00 2001 From: Andreas Tobler Date: Wed, 10 Dec 2014 20:23:19 +0000 Subject: [PATCH 12/13] Fix kernel build for booke. --- sys/powerpc/booke/trap.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sys/powerpc/booke/trap.c b/sys/powerpc/booke/trap.c index 476f77f522fe..eacd3e789f10 100644 --- a/sys/powerpc/booke/trap.c +++ b/sys/powerpc/booke/trap.c @@ -48,6 +48,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include From 1db9ecff02f75e6ba4c64c711ec2e4be83257e62 Mon Sep 17 00:00:00 2001 From: Enji Cooper Date: Wed, 10 Dec 2014 20:40:03 +0000 Subject: [PATCH 13/13] Remove termcap entry reordering; install the file verbatim instead termcap entry reordering requires ex (which is available via usr.bin/vi), which breaks on build hosts where installworld is run with MK_VI == no (or when make delete-old is run on ^/projects/building-blocks as vi, et al, are removed on the branch when the knob is tweaked to => "no") Reordering termcap was believed to improve performance, but the file is now accessed via /etc/termcap.db, so /etc/termcap (and /usr/share/misc/termcap by proxy) access is less preferred. Reordering the file broke the historical comment <-> entry mapping as well, which could muddle the purpose of entries in the file, so it could be potentially harmful to readers in its reordered state. Discussion took place on hackers@ here: https://lists.freebsd.org/pipermail/freebsd-hackers/2014-December/046657.html Discussed with: -hackers, mp MFC after: 1 month Sponsored by: EMC / Isilon Storage Division --- share/termcap/Makefile | 5 +-- share/termcap/README | 4 +- share/termcap/reorder | 62 -------------------------- share/termcap/{termcap.src => termcap} | 0 4 files changed, 4 insertions(+), 67 deletions(-) delete mode 100644 share/termcap/reorder rename share/termcap/{termcap.src => termcap} (100%) diff --git a/share/termcap/Makefile b/share/termcap/Makefile index 9f6e7189297d..1fdc5edf58ac 100644 --- a/share/termcap/Makefile +++ b/share/termcap/Makefile @@ -9,10 +9,7 @@ MAN= termcap.5 FILES= termcap termcap.db FILESDIR= ${BINDIR}/misc -CLEANFILES+= termcap termcap.db - -termcap: reorder termcap.src - TERM=dumb TERMCAP=dumb: ex - ${.CURDIR}/termcap.src < ${.CURDIR}/reorder +CLEANFILES+= termcap.db .include .if ${TARGET_ENDIANNESS} == "1234" diff --git a/share/termcap/README b/share/termcap/README index f299ce843655..c28d87fa811f 100644 --- a/share/termcap/README +++ b/share/termcap/README @@ -1,4 +1,6 @@ # @(#)README 8.1 (Berkeley) 6/8/93 +# +# $FreeBSD$ << 12 May 1983 >> To install this directory on your system: @@ -19,7 +21,7 @@ common and really should go near the front. Third, if you are not a super user and cannot create the directory /usr/lib/tabset, make a corresponding directory somewhere you can and add a line to reorder to globally change all /usr/lib/tabset's to your own -path name. This change is better than just changing the termcap.src file +path name. This change is better than just changing the termcap file because it makes it easier to diff it from newer distributed versions. Try to keep the source as is whenever possible, and put mungings into reorder. diff --git a/share/termcap/reorder b/share/termcap/reorder deleted file mode 100644 index 8fc94a755db3..000000000000 --- a/share/termcap/reorder +++ /dev/null @@ -1,62 +0,0 @@ -" $FreeBSD$ -/# << EOH -/k a -/^adm12|/;.,/^[^ ]/-m'a -/^pcplot/;.,/^[^ ]/-m'a -/^c100|/;.,/^[^ ]/-m'a -/^c100-rv|/;.,/^[^ ]/-m'a -/^c100-rv-pp|/;.,/^[^ ]/-m'a -/^c108-4p|/;.,/^[^ ]/-m'a -/^c108-rv-4p|/;.,/^[^ ]/-m'a -/^c108|/;.,/^[^ ]/-m'a -/^c108-rv-8p|/;.,/^[^ ]/-m'a -/^avt|/;.,/^[^ ]/-m'a -/^avt-rv|/;.,/^[^ ]/-m'a -/^avt-4p-s|/;.,/^[^ ]/-m'a -/^avt-8p-s|/;.,/^[^ ]/-m'a -/^ansi.sys|/;.,/^[^ ]/-m'a -/^ansi.sysk|/;.,/^[^ ]/-m'a -/^nansi.sys|/;.,/^[^ ]/-m'a -/^nansi.sysk|/;.,/^[^ ]/-m'a -/^h19k|/;.,/^[^ ]/-m'a -/^msk22714|/;.,/^[^ ]/-m'a -/^msk227am|/;.,/^[^ ]/-m'a -/^msk227|/;.,/^[^ ]/-m'a -/^pckermit120|/;.,/^[^ ]/-m'a -/^pckermit|/;.,/^[^ ]/-m'a -/^kermitam|/;.,/^[^ ]/-m'a -/^kermit|/;.,/^[^ ]/-m'a -/^sun-17|/;.,/^[^ ]/-m'a -/^sun-24|/;.,/^[^ ]/-m'a -/^sun-34|/;.,/^[^ ]/-m'a -/^sun-48|/;.,/^[^ ]/-m'a -/^sun-e-s|/;.,/^[^ ]/-m'a -/^sun-s|/;.,/^[^ ]/-m'a -/^sun-e|/;.,/^[^ ]/-m'a -/^sun|/;.,/^[^ ]/-m'a -/^xterm|/;.,/^[^ ]/-m'a -/^adm3|/;.,/^[^ ]/-m'a -/^adm31|/;.,/^[^ ]/-m'a -/^adm3a|/;.,/^[^ ]/-m'a -/^tvi924vb|/;.,/^[^ ]/-m'a -/^tvi924|/;.,/^[^ ]/-m'a -/^tvi912|/;.,/^[^ ]/-m'a -/^920b|/;.,/^[^ ]/-m'a -/^tvi925vb|/;.,/^[^ ]/-m'a -/^tvi925|/;.,/^[^ ]/-m'a -/^vt100|/;.,/^[^ ]/-m'a -/^vt200|/;.,/^[^ ]/-m'a -/^hp|/;.,/^[^ ]/-m'a -/^hp2645|/;.,/^[^ ]/-m'a -/^2621-nl|/;.,/^[^ ]/-m'a -/^2621|/;.,/^[^ ]/-m'a -/^h29|/;.,/^[^ ]/-m'a -/^h19|/;.,/^[^ ]/-m'a -/^h19-u|/;.,/^[^ ]/-m'a -/^h19-us|/;.,/^[^ ]/-m'a -/^h19-e|/;.,/^[^ ]/-m'a -/^h19-g|/;.,/^[^ ]/-m'a -/^dmd|/;.,/^[^ ]/-m'a -/^s/;.,/^#/-m'a -'ad -w! termcap -q diff --git a/share/termcap/termcap.src b/share/termcap/termcap similarity index 100% rename from share/termcap/termcap.src rename to share/termcap/termcap