Skip to content

Instantly share code, notes, and snippets.

@dolohow
Last active February 19, 2019 00:16
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dolohow/29752a12108e18a3e0cf84aca8d0c79d to your computer and use it in GitHub Desktop.
Save dolohow/29752a12108e18a3e0cf84aca8d0c79d to your computer and use it in GitHub Desktop.
Oracle test for Solaris team
> 1) Write a C (C99) program which reads a standard input and prints each line in reversed order. Assume '\n' as line separator. Do not assume limit of number of character per line. Example:
>
> $ printf "123\nhello\n" | ./a.out
> 321
> olleh
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
void strrev(char *str, size_t n)
{
/* Because xor swap is less efficient on modern CPU */
for(size_t i = 0; i < n/2; ++i) {
char tmp = str[i];
str[i] = str[n - i - 1];
str[n - i - 1] = tmp;
}
}
int main()
{
FILE *stream = stdin;
size_t bufflen = 128;
char *buff = malloc(bufflen);
while (fgets(buff, bufflen, stream)) {
size_t slen = strlen(buff);
/*
* When last element is not a new line and stream is not
* EOF that means we exhausted buffer
*/
while (buff[slen - 1] != '\n' && !feof(stream)) {
/* Increase buffer twice the current length */
bufflen *= 2;
buff = realloc(buff, bufflen);
/* Continue where NULL terminator sits */
if (!fgets(&buff[slen], bufflen/2, stream))
break;
slen = strlen(buff);
}
/*
* New line characters acts as a separator, we don't
* want it to be reversed and precede our string.
* So let's terminate string earlier. \n will be
* added by puts at the end after all.
*/
if (buff[slen - 1] == '\n')
buff[--slen] = '\0';
strrev(buff, slen);
puts(buff);
}
free(buff);
return EXIT_SUCCESS;
}
> 2) Write a command line to compile a program consisting of two .c files.
gcc a.c b.c
> 3) Write short program in C to demonstrate stack overflow.
#include <stdio.h>
#include <sys/resource.h>
int main()
{
struct rlimit lim;
/* Get maximum stack size in bytes */
getrlimit(RLIMIT_STACK, &lim);
/* Allocate array of the maximum size of stack */
char stack_overflow[lim.rlim_cur];
/* Following call to printf will end up with SIGSEGV */
printf("Hello world");
}
> 4) Write a command line to link two object files and a math library (libm).
ld -dynamic-linker /lib64/ld-linux-x86-64.so.2 /usr/lib/crt1.o \
/usr/lib/crti.o /usr/lib/crtn.o --no-as-needed -lc -lm a.o b.o -o a.out
or
gcc a.o b.o -o a.out -lm
Where `a.o`, `b.o` are those two object files and `a.out` is a elf
executable output.
> 5) Name your 5 favourite C functions from standard C library.
printf, malloc, memcpy, rand, strtok
> 6) Write short program in C to demonstrate buffer overflow.
#include <string.h>
#include <stdio.h>
int main()
{
char src[] = "hello word, hello word";
char a[] = "foo foo foo";
char dest[2];
/*
* I intentionally do not copy null terminator so the result is
* better visible in printf
* */
memcpy(dest, src, 22);
/*
* Will print "o wordo foo" instead of "foo" due to buffer
* overflow * which will cause overwrite the place where
* char *a is.
* */
printf("%s\n", a);
/*
* Due to alignment there is 16 bytes difference in their
* addresses which means 6 first bytes of char * (22 - 16) will
* be overwritten so the result is clear.
*
* foo foo foo
* hello word, hello word
* o wordo foo
* */
printf("dest: 0x%x\n", &dest);
printf("a: 0x%x\n", &a);
}
> 7) How to compile a C program with debug symbols?
gcc a.c -g
> 8) How one can strip debug symbols from a binary?
strip --strip-debug a.out
> 9) Write a makefile with targets to compile a program (e.g. from question 1) and do a clean up.
SRCS = main.c
EXECUTABLES = main
OBJS=$(SRCS:.c=.o)
CC=gcc
CFLAGS=-Wall -std=c99
all: $(EXECUTABLES)
$(EXECUTABLES): $(OBJS)
$(CC) $(CFLAGS) $(OBJS) -o $@
.c.o:
$(CC) $(CFLAGS) -c $< -o $@
clean:
rm -rf $(EXECUTABLES) $(OBJS)
Note: I had all those programs in one file so I could just create a
hardcoded target, but I suppose it would not be that
interesting seeing something like that.
main:
gcc -std=c99 main.c -o main
The following questions/tasks focus on your ability to run the appropriate
command from the command line (running /bin/sh or compatible [ksh, bash, ...]).
The answers should be one-liners if possible.
Note that it is not required to answer all the questions for the successful
application for the job.
Example:
Q: List all files in the current directory.
A: ls -a
1 Run the program "test.sh" and discard any output (standard and error)
of that script.
sh test.sh &> /dev/null
2 Copy a directory tree (with files) from /opt/test/ to your home
directory using tar.
tar cf - /opt/test | (cd ~/ && tar xf -)
3 Rename all .htm files in /tmp/test/ (but not subdirectories), so that
they have .html extension instead of .htm. Ignore hidden files.
find /tmp/test -maxdepth 1 -type f -not -path '*/\.*' -exec rename 's/\.htm$/\.html/' {} \;
Note: I am aware that rename programs differs, for example default
provider of rename on my Arch box comes from `util-linux`, but
for the purpose of solving this test I am using virtual machine
on Ubuntu and it comes from `perl`.
4 Print contents of all files in /tmp/test/ (but not subdirectories),
including hidden files. Ensure that the filesystem object is a regular
file.
find /tmp/test -maxdepth 1 -type f -exec cat {} +
5 List all files (their full paths) in /tmp/test/ and subdirectories,
that contain the left bracket "["
find /tmp/test -type f | grep "\["
6 You have a file "/tmp/test/IMPORTANT" and a new version of it in your
home directory named "IMPORTANT.new". Write a sequence of commands
that would replace the old version of the file with the new one,
and keep the backup named "/tmp/test/IMPORTANT.backup". There must
be no race condition (time slice when the file is not there, or when
there is just part of it).
ln /tmp/test/IMPORTANT /tmp/test/IMPORTANT.backup
mv ~/IMPORTANT.new /tmp/test/IMPORTANT
Note: I did some additional investigation concerning race condition.
I used `strace` while doing those two commands, first it calls
`stat` and `lstat` and then
linkat(AT_FDCWD, "/tmp/test/IMPORTANT", AT_FDCWD, "/tmp/test/IMPORTANT.backup", 0) = 0
which is atomic. `mv` is atomic too, because it calls rename
along with `lstat` and `stat`.
rename("/home/vagrant/IMPORTANT.new", "/tmp/test/IMPORTANT") = 0
The `rename(2)` says that this operation is atomic.
7 Transfer directory "/tmp/test/" (and everything below) to a machine
named "orion" to directory "/var/tmp/test". Use ssh.
scp -r /tmp/test orion:/var/tmp/test
8 Force apache to reload its configuration by sending a signal to it;
"apache.pid" file is located in "/var/apache/".
kill -USR1 `cat /var/apache/apache.pid`
9 In "/tmp/test" and subdirs there are files with ".dat" extension (among
others). The files contain numbers separated by 0x0A (LF).
Print the smallest number from each of the file.
find -type f -regex ".*dat$" -exec sort -n {} \; | head -n1
10 There is a filesystem mounted on /usr containing new version of
binaries. Create a hard link "/bin/perl" for file "/usr/bin/perl".
ln /usr/bin/perl /bin/perl
Note: If /usr reside on a different volume/partition etc. than /bin
it is not possible to create hard link, only symbolic.
11 Set ownership to "root" group "sys" for directory "/tmp/test" and
everything below.
chown -R root:sys /tmp/test
12 Set rights for "/tmp/test/" tree (both files and directories), so that
the owner can read and write files (but not execute), group can only
read, and others are denied access altogether. The directories must
be accessible for owner and group only.
find /tmp/test -type d -exec chmod 750 {} \;
find /tmp/test -type f -exec chmod 640 {} \;
13 Write a shell glob matching all files (and other objects) in the
current directory, including hidden files, but not matching
the "." or ".."
!(..|.)
14 Set permissions for binary "/usr/local/bin/my_program", so that only
"root" and members of the "adm" group can execute it; and when
executed, the program runs under "daemon" UID.
chown daemon:adm /usr/local/bin/my_program
chmod a-x,u+x,g+x /usr/local/bin/my_program
chmod u+s /usr/local/bin/my_program
15 Set permissions for "/tmp/test/", so that root cannot delete files in
this directory.
chattr -R +i test
Note: This is more like a prevent deleting by accident. Nothing stops
root from unsetting this attribute. In addition one can have
filesystem which does not support this. If /tmp/test could be
mounted read-only then this is another option, but again,
nothing stops root. Another option would be to experiment with
SELinux policies and allow modifying them after reboot.
16 List lines in file "/tmp/test/pkgs" that start with SUNW then a
hexadecimal number followed by a space, and end with an asterisk.
grep -P "^SUNW[0-9a-fA-F]+ \*$" /tmp/test/pkgs
Note: I assumed that hexadecimal number looks like 1AF or 1af, not
0x1af.
17 Copy file "/tmp/test/pkgs" to your home directory, so that the new name
is pkgs-YYYYMMDD (where YYYYMMDD is the current date).
cp /tmp/test/pkgs ~/pkgs-$(date +"%Y%m%d")
18 List user names from /etc/passwd that have UID > 500
awk -F: '{if ($3 > 500) print $1}' /etc/passwd
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment