Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F137757337
D51187.id158749.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
15 KB
Referenced Files
None
Subscribers
None
D51187.id158749.diff
View Options
diff --git a/stand/common/dev_net.c b/stand/common/dev_net.c
--- a/stand/common/dev_net.c
+++ b/stand/common/dev_net.c
@@ -66,6 +66,10 @@
#include "dev_net.h"
#include "bootstrap.h"
+#ifndef NETPROTO_DEFAULT
+# define NETPROTO_DEFAULT NET_NFS
+#endif
+
static char *netdev_name;
static int netdev_sock = -1;
static int netdev_opens;
@@ -303,7 +307,7 @@
return (EIO);
}
exit:
- if ((rootaddr = net_parse_rootpath()) != INADDR_NONE)
+ if ((rootaddr = net_parse_rootpath()) != htonl(INADDR_NONE))
rootip.s_addr = rootaddr;
DEBUG_PRINTF(1,("%s: proto: %d\n", __func__, netproto));
@@ -348,7 +352,7 @@
* Parses the rootpath if present
*
* The rootpath format can be in the form
- * <scheme>://ip/path
+ * <scheme>://ip[:port]/path
* <scheme>:/path
*
* For compatibility with previous behaviour it also accepts as an NFS scheme
@@ -363,10 +367,10 @@
uint32_t
net_parse_rootpath(void)
{
- n_long addr = htonl(INADDR_NONE);
+ n_long addr = 0;
size_t i;
char ip[FNAME_SIZE];
- char *ptr, *val;
+ char *ptr, *portp, *val;
netproto = NET_NONE;
@@ -381,7 +385,7 @@
ptr = rootpath;
/* Fallback for compatibility mode */
if (netproto == NET_NONE) {
- netproto = NET_NFS;
+ netproto = NETPROTO_DEFAULT;
(void)strsep(&ptr, ":");
if (ptr != NULL) {
addr = inet_addr(rootpath);
@@ -394,16 +398,21 @@
if (*ptr == '/') {
/* we are in the form <scheme>://, we do expect an ip */
ptr++;
- /*
- * XXX when http will be there we will need to check for
- * a port, but right now we do not need it yet
- */
+ portp = val = strchr(ptr, ':');
+ if (val != NULL) {
+ val++;
+ rootport = strtol(val, NULL, 10);
+ }
val = strchr(ptr, '/');
if (val != NULL) {
+ if (portp == NULL)
+ portp = val;
snprintf(ip, sizeof(ip), "%.*s",
- (int)((uintptr_t)val - (uintptr_t)ptr),
+ (int)((uintptr_t)portp - (uintptr_t)ptr),
ptr);
addr = inet_addr(ip);
+ DEBUG_PRINTF(1,("ip=%s addr=%#x\n",
+ ip, addr));
bcopy(val, rootpath, strlen(val) + 1);
}
} else {
@@ -411,6 +420,7 @@
bcopy(ptr, rootpath, strlen(ptr) + 1);
}
}
-
+ if (addr == 0)
+ addr = htonl(INADDR_NONE);
return (addr);
}
diff --git a/stand/common/install.c b/stand/common/install.c
--- a/stand/common/install.c
+++ b/stand/common/install.c
@@ -137,7 +137,9 @@
}
*p++ = '\0';
- if (strcmp(tag, "KERNEL") == 0)
+ if (strncmp(tag, "ENV_", 4) == 0)
+ setenv(&tag[4], val, 1);
+ else if (strcmp(tag, "KERNEL") == 0)
error = setpath(&inst_kernel, val);
else if (strcmp(tag, "MODULES") == 0)
error = setmultipath(&inst_modules, val);
@@ -288,6 +290,9 @@
} else
pkgname = s;
+ if (proto == NULL && netproto == NET_TFTP) {
+ proto = &tftp_fsops;
+ }
i = snprintf(buf, sizeof(buf), "%.*s:%s",
(int) devnamelen, devname, pkgname);
if (i >= (int) sizeof(buf)) {
diff --git a/stand/common/misc.c b/stand/common/misc.c
--- a/stand/common/misc.c
+++ b/stand/common/misc.c
@@ -199,8 +199,12 @@
if ((rv = devparse(&ncurr, value, NULL)) != 0)
return (rv);
+ rv = (ncurr->d_dev->dv_type == DEVT_NET);
free(ncurr);
-
+ if (rv != 0) {
+ env_setenv(ev->ev_name, flags | EV_NOHOOK, value, NULL, NULL);
+ return (0);
+ }
return (mount_currdev(ev, flags, value));
}
diff --git a/stand/defs.mk b/stand/defs.mk
--- a/stand/defs.mk
+++ b/stand/defs.mk
@@ -207,6 +207,8 @@
# Make sure we use the machine link we're about to create
CFLAGS+=-I.
+.include "${BOOTSRC}/veriexec.mk"
+
all: ${PROG}
CLEANFILES+= teken_state.h
diff --git a/stand/libsa/globals.c b/stand/libsa/globals.c
--- a/stand/libsa/globals.c
+++ b/stand/libsa/globals.c
@@ -17,6 +17,7 @@
u_char bcea[6] = BA; /* broadcast ethernet address */
char rootpath[FNAME_SIZE] = "/"; /* root mount path */
+int rootport = 0; /* port for rootpath server */
char bootfile[FNAME_SIZE]; /* bootp says to boot this */
char hostname[FNAME_SIZE]; /* our hostname */
int hostnamelen;
diff --git a/stand/libsa/net.h b/stand/libsa/net.h
--- a/stand/libsa/net.h
+++ b/stand/libsa/net.h
@@ -75,6 +75,7 @@
extern u_char bcea[6];
extern char rootpath[FNAME_SIZE];
+extern int rootport;
extern char bootfile[FNAME_SIZE];
extern char hostname[FNAME_SIZE];
extern int hostnamelen;
diff --git a/stand/libsa/open.c b/stand/libsa/open.c
--- a/stand/libsa/open.c
+++ b/stand/libsa/open.c
@@ -61,6 +61,7 @@
#include "stand.h"
struct fs_ops *exclusive_file_system;
+bool exclusive_file_system_devopen;
/*
* Open file list. The current implementation and assumption is,
@@ -154,27 +155,32 @@
f->f_devdata = NULL;
file = NULL;
+ if (exclusive_file_system == NULL ||
+ exclusive_file_system_devopen) {
+ error = devopen(f, fname, &file);
+ if (error ||
+ (((f->f_flags & F_NODEV) == 0) && f->f_dev == NULL))
+ goto err;
+
+ /* see if we opened a raw device; otherwise, 'file' is the file name. */
+ if (file == NULL || *file == '\0') {
+ f->f_flags |= F_RAW;
+ f->f_rabuf = NULL;
+ TSEXIT();
+ return (fd);
+ }
+ } else
+ file = fname;
+
if (exclusive_file_system != NULL) {
+ /* loader is forcing the filesystem to be used */
fs = exclusive_file_system;
- error = (fs->fo_open)(fname, f);
+ error = (fs->fo_open)(file, f);
if (error == 0)
goto ok;
goto err;
}
- error = devopen(f, fname, &file);
- if (error ||
- (((f->f_flags & F_NODEV) == 0) && f->f_dev == NULL))
- goto err;
-
- /* see if we opened a raw device; otherwise, 'file' is the file name. */
- if (file == NULL || *file == '\0') {
- f->f_flags |= F_RAW;
- f->f_rabuf = NULL;
- TSEXIT();
- return (fd);
- }
-
/* pass file name to the different filesystem open routines */
besterror = ENOENT;
for (i = 0; file_system[i] != NULL; i++) {
diff --git a/stand/libsa/pkgfs.c b/stand/libsa/pkgfs.c
--- a/stand/libsa/pkgfs.c
+++ b/stand/libsa/pkgfs.c
@@ -162,6 +162,9 @@
exclusive_file_system = proto;
+ /* there is no dev for pkgfs_fsops */
+ exclusive_file_system_devopen = (proto != &pkgfs_fsops);
+
fd = open(pkgname, O_RDONLY);
exclusive_file_system = NULL;
diff --git a/stand/libsa/stand.h b/stand/libsa/stand.h
--- a/stand/libsa/stand.h
+++ b/stand/libsa/stand.h
@@ -435,6 +435,7 @@
extern time_t getsecs(void);
extern struct fs_ops *file_system[];
extern struct fs_ops *exclusive_file_system;
+extern bool exclusive_file_system_devopen;
extern struct devsw *devsw[];
/*
diff --git a/stand/libsa/tftp.c b/stand/libsa/tftp.c
--- a/stand/libsa/tftp.c
+++ b/stand/libsa/tftp.c
@@ -50,6 +50,10 @@
#include <netinet/in_systm.h>
#include <arpa/tftp.h>
+#ifdef LOADER_VERIEXEC
+#include <verify_file.h>
+#endif
+
#include <string.h>
#include "stand.h"
@@ -84,7 +88,6 @@
};
static int tftpport = 2000;
-static int is_open = 0;
/*
* The legacy TFTP_BLKSIZE value was SEGSIZE(512).
@@ -98,10 +101,14 @@
* Jumbo frames in the future.
*/
#define TFTP_MAX_BLKSIZE 9008
-#define TFTP_TRIES 2
+#define TFTP_TRIES 3
struct tftp_handle {
struct iodesc *iodesc;
+ struct iodesc io;
+ int id;
+ ino_t ino;
+ int port;
int currblock; /* contents of lastdata */
unsigned int islastblock:1; /* flag */
unsigned int tries:4; /* number of read attempts */
@@ -177,6 +184,9 @@
wbuf.t.th_block = htons(block);
wtail += 2;
+ DEBUG_PRINTF(5,("%s: myport=%hu xid=%lu, block=%hu\n",
+ __func__, h->iodesc->myport, h->iodesc->xid, block));
+
sendudp(h->iodesc, &wbuf.t, wtail - (char *)&wbuf.t);
}
@@ -190,6 +200,7 @@
void *ptr = NULL;
ssize_t len;
int tftp_error;
+ unsigned short block;
errno = 0;
extra = recv_extra;
@@ -203,19 +214,22 @@
}
extra->rtype = ntohs(t->th_opcode);
- switch (ntohs(t->th_opcode)) {
+ block = ntohs(t->th_block);
+ DEBUG_PRINTF(6,("%s: myport=%hu xid=%lu, block=%hu, opcode=%hu\n",
+ __func__, d->myport, d->xid, block, extra->rtype));
+ switch (extra->rtype) {
case DATA: {
int got;
- if (htons(t->th_block) < (u_short)d->xid) {
+ if (block < (u_short)d->xid) {
/*
* Apparently our ACK was missed, re-send.
*/
- tftp_sendack(h, htons(t->th_block));
+ tftp_sendack(h, block);
free(ptr);
return (-1);
}
- if (htons(t->th_block) != (u_short)d->xid) {
+ if (block != (u_short)d->xid) {
/*
* Packet from the future, drop this.
*/
@@ -241,9 +255,7 @@
printf("illegal tftp error %d\n", tftp_error);
errno = EIO;
} else {
-#ifdef TFTP_DEBUG
- printf("tftp-error %d\n", tftp_error);
-#endif
+ DEBUG_PRINTF(0, ("tftp-error %d\n", tftp_error));
errno = tftperrors[tftp_error];
}
free(ptr);
@@ -284,9 +296,7 @@
return (0);
}
default:
-#ifdef TFTP_DEBUG
- printf("tftp type %d not handled\n", ntohs(t->th_opcode));
-#endif
+ DEBUG_PRINTF(0, ("tftp type %hu not handled\n", extra->rtype));
free(ptr);
return (-1);
}
@@ -343,7 +353,7 @@
bcopy("0", wtail, 2);
wtail += 2;
- h->iodesc->myport = htons(tftpport + (getsecs() & 0x3ff));
+ h->iodesc->myport = htons(h->port + (getsecs() & 0x3ff));
h->iodesc->destport = htons(IPPORT_TFTP);
h->iodesc->xid = 1; /* expected block */
@@ -351,11 +361,15 @@
h->islastblock = 0;
h->validsize = 0;
+ DEBUG_PRINTF(5,("%s: %s: id=%d port=%d myport=%hu xid=1\n",
+ __func__, h->path, h->id, h->port, ntohs(h->iodesc->myport)));
pkt = NULL;
recv_extra.tftp_handle = h;
res = sendrecv(h->iodesc, &sendudp, &wbuf.t, wtail - (char *)&wbuf.t,
&recvtftp, &pkt, (void **)&t, &recv_extra);
if (res == -1) {
+ DEBUG_PRINTF(3,("%s: %s: id=%d errno=%d\n",
+ __func__, h->path, h->id, errno));
free(pkt);
return (errno);
}
@@ -410,12 +424,18 @@
h->iodesc->xid = h->currblock + 1; /* expected block */
+ DEBUG_PRINTF(5,("%s: %s: id=%d port=%d myport=%hu xid=%lu\n",
+ __func__, h->path, h->id, h->port,
+ ntohs(h->iodesc->myport), h->iodesc->xid));
+
pkt = NULL;
recv_extra.tftp_handle = h;
res = sendrecv(h->iodesc, &sendudp, &wbuf.t, wtail - (char *)&wbuf.t,
&recvtftp, &pkt, (void **)&t, &recv_extra);
if (res == -1) { /* 0 is OK! */
+ DEBUG_PRINTF(3,("%s: %s: id=%d errno=%d\n",
+ __func__, h->path, h->id, errno));
free(pkt);
return (errno);
}
@@ -428,21 +448,32 @@
if (res < h->tftp_blksize)
h->islastblock = 1; /* EOF */
- if (h->islastblock == 1) {
+ DEBUG_PRINTF(5,("%s: %s: id=%d res=%d blksz=%d last=%d\n",
+ __func__, h->path, h->id, res, h->tftp_blksize, h->islastblock));
+
+ if (h->islastblock) {
/* Send an ACK for the last block */
- wbuf.t.th_block = htons((u_short)h->currblock);
- sendudp(h->iodesc, &wbuf.t, wtail - (char *)&wbuf.t);
+ tftp_sendack(h, h->currblock);
}
return (0);
}
+/*
+ * If doing verification we need to handle multiple
+ * files at the same time.
+ */
+#define TOPEN_MAX 8
+static struct tftp_handle *handles[TOPEN_MAX];
+
static int
tftp_open(const char *path, struct open_file *f)
{
struct devdesc *dev;
struct tftp_handle *tftpfile;
struct iodesc *io;
+ static int lx = 0;
+ int i, x;
int res;
size_t pathsize;
const char *extraslash;
@@ -450,24 +481,39 @@
if (netproto != NET_TFTP)
return (EINVAL);
- if (f->f_dev->dv_type != DEVT_NET)
+ if (f->f_dev == NULL || f->f_dev->dv_type != DEVT_NET)
return (EINVAL);
- if (is_open)
+ tftpfile = NULL;
+ for (x = lx + 1, i = 0; i < TOPEN_MAX; i++, x++) {
+ x %= TOPEN_MAX;
+ if (handles[x] == NULL) {
+ handles[x] = tftpfile = calloc(1, sizeof(*tftpfile));
+ if (tftpfile == NULL)
+ return (ENOMEM);
+ /* id allows us to clear the slot on close */
+ tftpfile->id = lx = x;
+ /* port ensures a different session with server */
+ tftpfile->port = (tftpport + (x * tftpport)) & 0xffff;
+ DEBUG_PRINTF(1, ("%s(%s) id=%d port=%d\n",
+ __func__, path, tftpfile->id, tftpfile->port));
+ break;
+ }
+ }
+ if (tftpfile == NULL) {
+ DEBUG_PRINTF(1, ("%s: EBUSY\n", __func__));
return (EBUSY);
-
- tftpfile = calloc(1, sizeof(*tftpfile));
- if (!tftpfile)
- return (ENOMEM);
-
+ }
tftpfile->tftp_blksize = TFTP_REQUESTED_BLKSIZE;
dev = f->f_devdata;
- tftpfile->iodesc = io = socktodesc(*(int *)(dev->d_opendata));
+ io = socktodesc(*(int *)(dev->d_opendata));
if (io == NULL) {
free(tftpfile);
return (EINVAL);
}
+ memcpy(&tftpfile->io, io, sizeof(tftpfile->io));
+ io = tftpfile->iodesc = &tftpfile->io;
io->destip = rootip;
tftpfile->off = 0;
pathsize = (strlen(rootpath) + 1 + strlen(path) + 1) * sizeof(char);
@@ -480,8 +526,11 @@
extraslash = "";
else
extraslash = "/";
- res = snprintf(tftpfile->path, pathsize, "%s%s%s",
- rootpath, extraslash, path);
+ if (rootpath[0] == '/' && rootpath[1] == '\0' && path[0] == '/')
+ res = strlcpy(tftpfile->path, path, pathsize);
+ else
+ res = snprintf(tftpfile->path, pathsize, "%s%s%s",
+ rootpath, extraslash, path);
if (res < 0 || res > pathsize) {
free(tftpfile->path);
free(tftpfile);
@@ -491,13 +540,13 @@
res = tftp_makereq(tftpfile);
if (res) {
+ handles[tftpfile->id] = NULL;
free(tftpfile->path);
free(tftpfile->pkt);
free(tftpfile);
return (res);
}
f->f_fsdata = tftpfile;
- is_open = 1;
return (0);
}
@@ -547,9 +596,7 @@
rc = tftp_getnextblock(tftpfile);
if (rc) { /* no answer */
-#ifdef TFTP_DEBUG
- printf("tftp: read error\n");
-#endif
+ DEBUG_PRINTF(0, ("tftp: read error\n"));
if (tftpfile->tries > TFTP_TRIES) {
return (rc);
} else {
@@ -568,10 +615,8 @@
inbuffer = tftpfile->validsize - offinblock;
if (inbuffer < 0) {
-#ifdef TFTP_DEBUG
- printf("tftp: invalid offset %d\n",
- tftpfile->off);
-#endif
+ DEBUG_PRINTF(0, ("tftp: invalid offset %d\n",
+ tftpfile->off));
return (EINVAL);
}
count = (size < inbuffer ? size : inbuffer);
@@ -586,15 +631,15 @@
if ((tftpfile->islastblock) && (count == inbuffer))
break; /* EOF */
} else {
-#ifdef TFTP_DEBUG
- printf("tftp: block %d not found\n", needblock);
-#endif
+ DEBUG_PRINTF(0, ("tftp: block %d not found\n", needblock));
return (EINVAL);
}
}
out:
+ DEBUG_PRINTF(4, ("%s(%s) res=%ld\n", __func__, tftpfile->path,
+ (tftpfile->tftp_tsize - tftpfile->off)));
if (resid != NULL)
*resid = res;
return (rc);
@@ -610,15 +655,18 @@
tftp_senderr(tftpfile, 0, "No error: file closed");
if (tftpfile) {
+ DEBUG_PRINTF(1, ("%s(%d): %s\n", __func__,
+ tftpfile->id, tftpfile->path));
+ handles[tftpfile->id] = NULL;
free(tftpfile->path);
free(tftpfile->pkt);
free(tftpfile->tftp_cache);
free(tftpfile);
}
- is_open = 0;
return (0);
}
+
static int
tftp_stat(struct open_file *f, struct stat *sb)
{
@@ -630,6 +678,29 @@
sb->st_uid = 0;
sb->st_gid = 0;
sb->st_size = tftpfile->tftp_tsize;
+ sb->st_mtime = 0;
+#ifdef LOADER_VERIEXEC
+ /* libsecureboot needs st_dev and st_ino at minimum;
+ * we need to fake something that will be close enough to
+ * unique.
+ */
+ sb->st_dev = (dev_t)tftpfile->iodesc->destip.s_addr;
+ /* we don't want to compute this more than once */
+ if (tftpfile->ino == 0) {
+ union {
+ unsigned char digest[SHA_DIGEST_LENGTH];
+ ino_t ino;
+ } u;
+
+ hash_string(tftpfile->path, 0, u.digest, sizeof(u.digest));
+
+ tftpfile->ino = u.ino & 0x7fffffff;
+ DEBUG_PRINTF(2,("%s(%s) dev=%lu ino=%lu\n", __func__,
+ tftpfile->path, (unsigned long)sb->st_dev,
+ (unsigned long)tftpfile->ino));
+ }
+ sb->st_ino = tftpfile->ino;
+#endif
return (0);
}
@@ -827,9 +898,7 @@
return (-1);
}
-#ifdef TFTP_DEBUG
- printf("tftp_blksize: %u\n", h->tftp_blksize);
- printf("tftp_tsize: %lu\n", h->tftp_tsize);
-#endif
+ DEBUG_PRINTF(2, ("tftp_blksize: %u\n", h->tftp_blksize));
+ DEBUG_PRINTF(2, ("tftp_tsize: %lu\n", h->tftp_tsize));
return (0);
}
diff --git a/stand/loader.mk b/stand/loader.mk
--- a/stand/loader.mk
+++ b/stand/loader.mk
@@ -101,8 +101,6 @@
.error Unknown interpreter ${LOADER_INTERP}
.endif
-.include "${BOOTSRC}/veriexec.mk"
-
.if defined(BOOT_PROMPT_123)
CFLAGS+= -DBOOT_PROMPT_123
.endif
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Wed, Nov 26, 1:40 PM (15 h, 22 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
26213494
Default Alt Text
D51187.id158749.diff (15 KB)
Attached To
Mode
D51187: Allow secure-netboot
Attached
Detach File
Event Timeline
Log In to Comment