In the installation guide of some soft, user is told to run this
sudo ln -s /opt/local/somesoft/somsoft* /opt/local/bin
Is this command dangerous ? Should /opt/local/bin be prevented from calling something else tha n itself ?
This command does few things
sudo gives root permissions to the 'ln' binary
ln is instructed to go through all files matching pattern /opt/local/somesoft/somsoft*
for every such file it tries to create symbolic link in /opt/local/bin directory
this created symbolic link will have the same name as the file just being processed
Your first question is, is it dangerous? Most probably not, there are few things which might go wrong
your $PATH environment contains some strange directory, so instead of calling /usr/bin/ln (as was the original intention I believe) you wold be tricked into calling some different executable. For example if your PATH=.:/tmp:/usr/bin, 'ln' is first searched in your current directory, then in /tmp and then in /usr/bin. And it's called with superuser permissions ...
there are no such files as /opt/local/somesoft/somsoft* . In such case ln will create symbolic link '/opt/local/bin/somsoft*' (including the star in it's name). That's probably not what you wanted
/opt/local/bin already contains the files with the same names as /opt/local/somesoft/somsoft* . In such case ln will not create new files there (is it good or bad? that is the question)
You don't have /opt/local/bin . In such cases there are several ways of how the command fails (depending whether you have /opt/local directory and how many files match the pattern /opt/local/somesoft/somsoft*)
Your second question does not make much sense. /opt/local/bin is a directory, and directory can't "call" anything. So it can't be prevented to do so. If you ask whether the symbolic links should be created there, I would say why not. The whole idea behind the command is to
install somesoft into special directory so that you won't pollute your /usr/bin or any other common directory
to be able to run the commands without the need of specifying every time full path /opt/local/somesoft/somsoft... you may want to create symbolic links in /opt/local/bin. And make sure that your /opt/local/bin is in your directory.
Related
I feel like I'm missing something very basic so apologies if this question is obtuse. I've been struggling with this problem for as long as I've been using the bash shell.
Say I have a structure like this:
├──bin
├──command (executable)
This will execute:
$ bin/command
then I symlink bin/command to the project root
$ ln -s bin/command c
like so
├──c (symlink to bin/command)
├──bin
├──command (executable)
I can't do the following (errors with -bash: c: command not found)
$ c
I must do?
$ ./c
What's going on here? — is it possible to execute a command from the current directory without preceding it with ./ and also without using a system wide alias? It would be very convenient for distributed executables and utility scripts to give them one letter folder specific shortcuts on a per project basis.
It's not a matter of bash not allowing execution from the current directory, but rather, you haven't added the current directory to your list of directories to execute from.
export PATH=".:$PATH"
$ c
$
This can be a security risk, however, because if the directory contains files which you don't trust or know where they came from, a file existing in the currently directory could be confused with a system command.
For example, say the current directory is called "foo" and your colleague asks you to go into "foo" and set the permissions of "bar" to 755. As root, you run "chmod foo 755"
You assume chmod really is chmod, but if there is a file named chmod in the current directory and your colleague put it there, chmod is really a program he wrote and you are running it as root. Perhaps "chmod" resets the root password on the box or something else dangerous.
Therefore, the standard is to limit command executions which don't specify a directory to a set of explicitly trusted directories.
Beware that the accepted answer introduces a serious vulnerability!
You might add the current directory to your PATH but not at the beginning of it. That would be a very risky setting.
There are still possible vulnerabilities when the current directory is at the end but far less so this is what I would suggest:
PATH="$PATH":.
Here, the current directory is only searched after every directory already present in the PATH is explored so the risk to have an existing command overloaded by an hostile one is no more present. There is still a risk for an uninstalled command or a typo to be exploited, but it is much lower. Just make sure the dot is always at the end of the PATH when you add new directories in it.
You could add . to your PATH. (See kamituel's answer for details)
Also there is ~/.local/bin for user specific binaries on many distros.
What you can do is add the current dir (.) to the $PATH:
export PATH=.:$PATH
But this can pose a security issue, so be aware of that. See this ServerFault answer on why it's not so good idea, especially for the root account.
kdevelop provides this AppImage binary:
wget -O KDevelop.AppImage https://download.kde.org/stable/kdevelop/5.1.1/bin/linux/KDevelop-5.1.1-x86_64.AppImage
chmod +x KDevelop.AppImage
./KDevelop.AppImage
It works well. So I want to make a soft link called kd to that binary in /usr/bin, eg:
/usr/bin/sudo ln -s KDevelop-5.1.1-x86_64.AppImage kd
Now if I run kd file1, I'd expect that it would open a file name file1 in the current folder, but it always tries to open a file name file1 in my home folder - which is not where it should be.
Is there some way to fix this issue?
Some possible causes:
The application always assumes that you want to open files in your home directory, effectively or literally prepending $HOME to the path. This would be a bug in any *nix program, and should be reported.
The application behaves differently when $(basename "$0") is not KDevelop.AppImage (what #Scheff said).
You are actually running a different kd.
Possible workarounds/investigations:
Pass the full path to the file on the command line. If it tries to open /home/you//full/path/you/provided it is obviously buggy, and you have a test case. If it does not, then there might be some gotcha to what your $PWD actually is. Try checking its value before running.
Symlink with the same name, using sudo ln -s KDevelop-5.1.1-x86_64.AppImage /usr/bin, and try running that. If it behaves the same, you've at least proven that the symlink is not the problem.
Run type -a kd and verify that your /usr/bin/kd comes up first. If not there might be an alias or shell built-in which takes precedence.
That said, what is the actual error message?
If I create a symlink through
ln -s /path/to/linked/dir current/path/link_name
and change the directory to current/path/link_name via
cd link_name
then I can check where I am using pwd-command. The output will be
current/path/link_name
But if I use some terminal emulator, such as terminator, konsole or others, I can split the tab or create a new tab in the same directory. The output of the pwd-command in the newly created tab will be
/path/to/linked/dir
In many cases, this is not convenient. Does anybody know how to change this behaviour in some terminal emulator(s)?
P.S. I also noticed that the output of ls typed from /current/path/link_name is the same as the output of ls typed from /path/to/linked/dir.
You can't. The reason is that you lose the information on how did you get there after the system call has executed. Some terminal emulators and mainly the bash(1) shell try to remember this, and implement pwd as an internal command, to cope with this scenarios. But in general if you try
/bin/pwd
You'll discover that all the information about how did you get to that final directory was lost in the course of time.
Ask yourself how can the /bin/pwd work and how can it determine the directory you are on, and you'll answer yourself the question:
The system maintains a current directory (the pwd command inherits this from its parent shell) in the system data for each process, but to save resources, it only stores the inode number of the directory that is actually your current directory (not actually, it maintains a reference to the in-core inode structure). It doesn't store the path you used to locate it, and it stores that info only to be able to get a starting point when you ask for a relative path when opening a file. The problem is the same as determining which directory a multiple linked file belongs to... no parent directory is stored for a file, as it can be in multiple directories linking to it all at the same time... this is also true for directories, but they have an .. entry inside themselves that links to their parents (their true parents, as one directory is now allowed to belong to different directories by means on normal links, this is forbidden by system, and ensured by the mkdir(2) system call) The pwd(1) commands uses precisely these links to find the parent directory (and then find the current dir in the parent directory, by searching for the inode number of the current directory on it), until this algorithm leads to the same inode (the root directory has this special characteristic, its .. entry points again to itself) so it stops going up. pwd can only work because it is following directories, and never files.
Terminator 1.90 does what you want. In an example session:
$ cd -- "$(mktemp --directory)"
$ mkdir a
$ ln -s a b
$ cd b
Press Ctrl-Shift-e (or o, or t). At this point I'm still in b.
I need to use mkfs.vfat in Makefile mymake.mk,
but this command is locate in /sbin/
$ which mkfs.vfat
/sbin/mkfs.vfat
current user is not root, and I build my project then got error "command not found".
How to use sbin command in Makefile?
The problem you have is probably these two points:
The current user does not have /sbin/ in his $PATH.
The current user is not allowed to write to the block device to create a file system on it.
The first problem is easily amended by just writing the full path instead of just the command in the Makefile:
target: sources …
/sbin/mkfs.vfat ……
The second problem only occurs if you really want to write to a block device you haven't write permissions to. In this case consider what you are doing. Does it really make sense? Typically this makes only sense in a make install situation, and this should be executed by user root only, so then you'd have write permissions. In practice, one typically types sudo make install to gain root access for that installation step only.
If, however, this is a special case, then you can add that sudo to your Makefile as well:
target: sources …
sudo /sbin/mkfs.vfat ……
(This would lead to being asked for the password when running the Makefile.)
And, last not least, you can use that mkfs to create a file, containing the newly created file system. In that case you don't need any special permissions (besides write permissions to that file you want to create:
target: sources …
/sbin/mkfs.vfat -C /path/to/my/filesystem ……
Have somewhere in the header
PATH:=$(PATH):/sbin
I have a file called x.sh that I want to execute. If I run:
x.sh
then I get:
x.sh: command not found
If I run:
./x.sh
then it runs correctly. Why do I have to type in ./ first?
Because the current directory is not into the PATH environment variable by default, and executables without a path qualification are searched only inside the directory specified by PATH. You can change this behavior by adding . to the end of PATH, but it's not common practice, you'll just get used to this UNIXism.
The idea behind this is that, if executables were searched first inside the current directory, a malicious user could put inside his home directory an executable named e.g. ls or grep or some other commonly used command, tricking the administrator to use it, maybe with superuser powers. On the other hand, this problem is not much felt if you put . at the end of PATH, since in that case the system directories are searched first.
But: our malicious user could still create his dangerous scripts named as common typos of often used commands, e.g. sl for ls (protip: bind it to Steam Locomotive and you won't be tricked anyway :D).
So you see that it's still better to be safe that, if you type an executable name without a path qualification, you are sure you're running something from system directories (and thus supposedly safe).
Because the current directory is normally not included in the default PATH, for security reasons: by NOT looking in the current directory all kinds of nastiness that could be caused by planting a malicious program with the name of a legitimate utility can be avoided. As an example, imagine someone manages to plant a script called ls in your directory, and that script executes rm *.
If you wish to include the current directory in your path, and you're using bash as your default shell, you can add the path via your ~/.bashrc file.
export PATH=$PATH:.
Based on the explanation above, the risk posed by rogue programs is reduced by looking in . last, so all well known legitimate programs will be found before . is checked.
You could also modify the systemwide settings via /etc/profile but that's probably not a good idea.
Because current directory is not in PATH (unlike cmd in Windows). It is a security feature so that malicious scripts in your current directory are not accidentally run.
Though it is not advisable, to satisfy curiosity, you can add . to the PATH and then you will see that x.sh will work.
If you don't explicitly specify a directory then the shell searches through the directories listed in your $PATH for the named executable. If your $PATH does not include . then the current directory is not searched.
$ echo $PATH
/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin:/usr/X11/bin
This is on purpose. If the current directory were searched then the command you type could potentially change based on what directory you're in. This would allow a malicious user to place a binary named ls or cp into directories you frequent and trick you into running a different program.
$ cat /tmp/ls
rm -rf ~/*
$ cd /tmp
$ ls
*kaboom*
I strongly recommend you not add . to your $PATH. You will quickly get used to typing ./, it's no big deal.
You can't execute your file by typing simply
x.sh
because the present working directory isn't in your $PATH. To see your present working directory, type
$ pwd
To see your $PATH, type
$ echo $PATH
To add the current directory to your $PATH for this session, type
$ PATH=$PATH:.
To add it permanently, edit the file .profile in your home directory.