[syslinux:elflink] core: Fix ldlinux.c32 failing to load when not installed in "/"

syslinux-bot for Matt Fleming matt.fleming at linux.intel.com
Thu Jul 28 14:06:14 PDT 2011


Commit-ID:  833f2859a77ed0d14ee197fe6e9d67044d5200c1
Gitweb:     http://syslinux.zytor.com/commit/833f2859a77ed0d14ee197fe6e9d67044d5200c1
Author:     Matt Fleming <matt.fleming at linux.intel.com>
AuthorDate: Tue, 12 Jul 2011 11:52:05 +0100
Committer:  Matt Fleming <matt.fleming at linux.intel.com>
CommitDate: Tue, 12 Jul 2011 16:24:06 +0100

core: Fix ldlinux.c32 failing to load when not installed in "/"

Currently, if syslinux is installed in a directory other than "/" we
will fail to load ldlinux.c32.

Because we know where we were installed the simplest fix is to chdir()
to the installation directory before attempting to load
ldlinux.c32. This requires us to add "." to PATH so that we look in
the current working directory when loading ELF modules.

Changing to the install directory needs to handled differently for
different file systems, which is the reason behind the new file system
operation, .chdir_start(). Disk-based Syslinux variants should use
generic_chdir_start() to chdir() to CurrentDirName, which is the
installation path. By using this new fs operation, we can load
ldlinux.c32 when we expand the "."  in PATH, without having to search
the entire filesystem for it. However, iso9660 file systems still
require us to search some directories because it has no notion of an
installation directory.

Previously, changing into the install directory was handled when
opening the config file, but because the config file parser is now
part of the ldlinux.c32 ELF module, it needs to be done much earlier.

Reported-by: H. Peter Anvin <hpa at zytor.com>
Signed-off-by: Matt Fleming <matt.fleming at linux.intel.com>


---
 com32/lib/sys/file.h          |    1 +
 com32/lib/sys/module/common.c |    9 +++++++++
 core/elflink/load_env32.c     |   35 +++++++++++++++++++++++++++++++++++
 core/fs/btrfs/btrfs.c         |    1 +
 core/fs/ext2/ext2.c           |    1 +
 core/fs/fat/fat.c             |    1 +
 core/fs/fs.c                  |    9 ++++++---
 core/fs/lib/chdir.c           |    6 ++++++
 core/fs/pxe/pxe.c             |    8 +++++++-
 core/include/fs.h             |    4 ++++
 10 files changed, 71 insertions(+), 4 deletions(-)

diff --git a/com32/lib/sys/file.h b/com32/lib/sys/file.h
index e984f16..4cd1946 100644
--- a/com32/lib/sys/file.h
+++ b/com32/lib/sys/file.h
@@ -98,6 +98,7 @@ struct file_info {
 };
 
 extern struct file_info __file_info[NFILES];
+extern const struct input_dev __file_dev;
 
 /* Line input discipline */
 ssize_t __line_input(struct file_info *fp, char *buf, size_t bufsize,
diff --git a/com32/lib/sys/module/common.c b/com32/lib/sys/module/common.c
index 1afdbf5..b1bf2fc 100644
--- a/com32/lib/sys/module/common.c
+++ b/com32/lib/sys/module/common.c
@@ -74,6 +74,15 @@ again:
 	if (*p == ':')
 		p++;
 
+	if (!strcmp(path, ".")) {
+		if (!core_getcwd(path, sizeof(path))) {
+			DBG_PRINT("Could not get cwd\n");
+			return NULL;
+		}
+
+		i = strlen(path);
+	}
+
 	n = name;
 	while (*n && i < FILENAME_MAX)
 		path[i++] = *n++;
diff --git a/core/elflink/load_env32.c b/core/elflink/load_env32.c
index e639653..d7757f3 100644
--- a/core/elflink/load_env32.c
+++ b/core/elflink/load_env32.c
@@ -11,6 +11,10 @@
 #include <linux/list.h>
 #include <netinet/in.h>
 #include <sys/cpu.h>
+#include <core.h>
+#include <fcntl.h>
+#include <sys/file.h>
+#include <fs.h>
 
 #include <sys/exec.h>
 #include <sys/module.h>
@@ -68,12 +72,43 @@ static void call_constr(void)
 /* note to self: do _*NOT*_ use static key word on this function */
 void load_env32(com32sys_t * regs)
 {
+	struct file_info *fp;
+	int fd;
 	char *argv[] = { LDLINUX, NULL };
 
+	static const char *search_directories[] = {
+		"/boot/isolinux",
+		"/isolinux",
+		"/boot/syslinux",
+		"/syslinux",
+		"/",
+		NULL
+	};
+
+	static const char *filenames[] = {
+		LDLINUX,
+		NULL
+	};
+
 	dprintf("Starting 32 bit elf module subsystem...\n");
 	call_constr();
 
 	init_module_subsystem(&core_module);
 
 	spawn_load(LDLINUX, 1, argv);
+
+	/*
+	 * If we failed to load LDLINUX it could be because our
+	 * current working directory isn't the install directory. Try
+	 * a bit harder to find LDLINUX. If search_config() succeeds
+	 * in finding LDLINUX it will set the cwd.
+	 */
+	fd = opendev(&__file_dev, NULL, O_RDONLY);
+	if (fd < 0)
+		return;
+
+	fp = &__file_info[fd];
+
+	if (!search_config(&fp->i.fd, search_directories, filenames))
+		spawn_load(LDLINUX, 1, argv);
 }
diff --git a/core/fs/btrfs/btrfs.c b/core/fs/btrfs/btrfs.c
index bce9deb..8dedf8a 100644
--- a/core/fs/btrfs/btrfs.c
+++ b/core/fs/btrfs/btrfs.c
@@ -670,5 +670,6 @@ const struct fs_ops btrfs_fs_ops = {
     .mangle_name   = generic_mangle_name,
     .next_extent   = btrfs_next_extent,
     .readdir       = btrfs_readdir,
+    .chdir_start   = generic_chdir_start,
     .open_config   = generic_open_config
 };
diff --git a/core/fs/ext2/ext2.c b/core/fs/ext2/ext2.c
index 4c183e5..ea21100 100644
--- a/core/fs/ext2/ext2.c
+++ b/core/fs/ext2/ext2.c
@@ -326,6 +326,7 @@ const struct fs_ops ext2_fs_ops = {
     .getfssec      = generic_getfssec,
     .close_file    = generic_close_file,
     .mangle_name   = generic_mangle_name,
+    .chdir_start   = generic_chdir_start,
     .open_config   = generic_open_config,
     .iget_root     = ext2_iget_root,
     .iget          = ext2_iget,
diff --git a/core/fs/fat/fat.c b/core/fs/fat/fat.c
index 6343b01..fbc4386 100644
--- a/core/fs/fat/fat.c
+++ b/core/fs/fat/fat.c
@@ -787,6 +787,7 @@ const struct fs_ops vfat_fs_ops = {
     .getfssec      = generic_getfssec,
     .close_file    = generic_close_file,
     .mangle_name   = vfat_mangle_name,
+    .chdir_start   = generic_chdir_start,
     .open_config   = generic_open_config,
     .readdir       = vfat_readdir,
     .iget_root     = vfat_iget_root,
diff --git a/core/fs/fs.c b/core/fs/fs.c
index 52bcf5b..a4fb4f7 100644
--- a/core/fs/fs.c
+++ b/core/fs/fs.c
@@ -8,7 +8,7 @@
 #include "fs.h"
 #include "cache.h"
 
-char *PATH = "/:/bin/";
+char *PATH = ".:/bin/";
 
 /* The currently mounted filesystem */
 struct fs_info *this_fs = NULL;		/* Root filesystem */
@@ -78,8 +78,6 @@ void _close_file(struct file *file)
     free_file(file);
 }
 
-extern const struct input_dev __file_dev;
-
 /*
  * Find and open the configuration file
  */
@@ -490,6 +488,11 @@ void fs_init(com32sys_t *regs)
 	fs.cwd = get_inode(fs.root);
     }
 
+    if (fs.fs_ops->chdir_start) {
+	    if (fs.fs_ops->chdir_start() < 0)
+		    printf("Failed to chdir to start directory\n");
+    }
+
     SectorShift = fs.sector_shift;
     SectorSize  = fs.sector_size;
 }
diff --git a/core/fs/lib/chdir.c b/core/fs/lib/chdir.c
new file mode 100644
index 0000000..5c7b130
--- /dev/null
+++ b/core/fs/lib/chdir.c
@@ -0,0 +1,6 @@
+#include <core.h>
+
+int generic_chdir_start(void)
+{
+	return chdir(CurrentDirName);
+}
diff --git a/core/fs/pxe/pxe.c b/core/fs/pxe/pxe.c
index 3e5d172..573efe3 100644
--- a/core/fs/pxe/pxe.c
+++ b/core/fs/pxe/pxe.c
@@ -1047,6 +1047,12 @@ static int pxe_chdir(struct fs_info *fs, const char *src)
     return 0;
 }
 
+static int pxe_chdir_start(void)
+{
+	get_prefix();
+	return 0;
+}
+
 /* Load the config file, return -1 if failed, or 0 */
 static int pxe_open_config(struct com32_filedata *filedata)
 {
@@ -1056,7 +1062,6 @@ static int pxe_open_config(struct com32_filedata *filedata)
     char *last;
     int tries = 8;
 
-    get_prefix();
     if (DHCPMagic & 0x02) {
         /* We got a DHCP option, try it first */
 	if (!open_file(ConfigName, filedata))
@@ -1724,5 +1729,6 @@ const struct fs_ops pxe_fs_ops = {
     .getfssec      = pxe_getfssec,
     .close_file    = pxe_close_file,
     .mangle_name   = pxe_mangle_name,
+    .chdir_start   = pxe_chdir_start,
     .open_config   = pxe_open_config,
 };
diff --git a/core/include/fs.h b/core/include/fs.h
index 04451ed..a554a46 100644
--- a/core/include/fs.h
+++ b/core/include/fs.h
@@ -61,6 +61,7 @@ struct fs_ops {
     void     (*mangle_name)(char *, const char *);
     size_t   (*realpath)(struct fs_info *, char *, const char *, size_t);
     int      (*chdir)(struct fs_info *, const char *);
+    int      (*chdir_start)(void);
     int      (*open_config)(struct com32_filedata *);
 
     struct inode * (*iget_root)(struct fs_info *);
@@ -209,6 +210,9 @@ char *core_getcwd(char *buf, size_t size);
  * Generic functions that filesystem drivers may choose to use
  */
 
+/* chdir.c */
+int generic_chdir_start(void);
+
 /* mangle.c */
 void generic_mangle_name(char *, const char *);
 



More information about the Syslinux-commits mailing list